Как конвертировать Tuple в Async Task - PullRequest
1 голос
/ 26 марта 2019

Я делаю небольшое приложение и мне нужна помощь, потому что я не знаю, в чем проблема.

Я давно не был с C # и учусь понемногу, потому что все это - отдых для меня, не более.

У меня есть следующий кортеж, который работает правильно:

private Tuple<int, int, int, int> CheckStatus()
        {
            int out = 0;
            int stage = 0;
            int retired = 0;
            int stop = 0;
            for (int i = 0; i < Dgv.Rows.Count; i++)
            {
                if (Dgv.Rows[i].Cells["Start"].Value != null)
                {
                    out = out + 1;
                }
                if (Dgv.Rows[i].Cells["Start"].Value != null && Dgv.Rows[i].Cells["Finnish"].Value == null)
                {
                    stage = stage + 1;
                }
                if (Dgv.Rows[i].Cells["Start"].Value != null && Dgv.Rows[i].Cells["Finnish"].Value != null)
                {
                    stop = stop + 1;
                }
            }
            retired = GetRetirements();
            stage = stage - retired;
            return new Tuple<int, int, int,int>(out, stage, retired, stop);
        }

Я хочу передать его асинхронному для выполнения метода await, потому что теперь метод GetRetirements выполняет асинхронные задачи, и измените код на этот, но у меня есть проблемы:

private async Task<Tuple<int, int, int, int>> CheckStatus()
        {
            int out = 0;
            int stage = 0;
            int retired = 0;
            int stop = 0;
            for (int i = 0; i < Dgv.Rows.Count; i++)
            {
                if (Dgv.Rows[i].Cells["Start"].Value != null)
                {
                    out = out + 1;
                }
                if (Dgv.Rows[i].Cells["Start"].Value != null && Dgv.Rows[i].Cells["Finnish"].Value == null)
                {
                    stage = stage + 1;
                }
                if (Dgv.Rows[i].Cells["Start"].Value != null && Dgv.Rows[i].Cells["Finnish"].Value != null)
                {
                    stop = stop + 1;
                }
            }
            retired = await GetRetirements();
            stage = stage - retired;
            return new Tuple<int, int, int,int>(out, stage, retired, stop);
        }

Но говорит мне, что не может найти ни одного предмета (item1, item2, item3, item4). Я не знаю, в чем проблема.

private void GetCheckStatus()
        {
            LblOut.Text = CheckStatus().Item1.ToString();
            LblStage.Text = CheckStatus().Item2.ToString();
            LblRetired.Text = CheckStatus().Item3.ToString();
            LblStop.Text = CheckStatus().Item4.ToString();
        }

Я что-то не так делаю? Это первый раз, когда я работаю с Tuple, и я не знаю правду, что это может быть неправильно.

Большое спасибо.

С уважением,

Ответы [ 4 ]

2 голосов
/ 26 марта 2019

CheckStatus теперь асинхронная функция. Чтобы получить результат, вам нужно await, и вы, скорее всего, захотите вызвать функцию только один раз. Обратите внимание, как async также был добавлен к GetCheckStatus и будет проходить вплоть до обработчика событий async void, например, нажатие кнопки.

private async Task GetCheckStatus()
{
    var status = await CheckStatus()
    LblOut.Text = status.Item1.ToString();
    LblStage.Text = status.Item2.ToString();
    LblRetired.Text = status.Item3.ToString();
    LblStop.Text = status.Item4.ToString();
}
1 голос
/ 26 марта 2019

Вы сделали внутренний вызов асинхронным, но внешний вызов его не ждет. Попробуйте что-то вроде:

private async Task GetCheckStatus()
{
    var result = await CheckStatus();

    LblOut.Text = result .Item1.ToString();
    LblStage.Text = result .Item2.ToString();
    LblRetired.Text = result .Item3.ToString();
    LblStop.Text = result .Item4.ToString();
}
1 голос
/ 26 марта 2019

Вы изменили CheckStatus(), чтобы вернуть Task<>. Вы должны вероятно await это и использовать результат как прежде.

Вы также можете обрабатывать это по-разному, в зависимости от вашей инфраструктуры пользовательского интерфейса. Но все сводится к тому, что «этот метод теперь aysnc, обработайте его таким образом».

0 голосов
/ 28 марта 2019

Причина в том, что вы забыли дождаться результатов CheckStatus() перед тем, как получить доступ к результату.

Обычно асинхронные функции заканчиваются именем async.Это сделано для того, чтобы предупредить пользователей о том, что они не должны забывать, что они используют async-await и что им следует дождаться возвращаемого значения, прежде чем получить доступ к результату.

Это также дает то преимущество, что вы можете предложить как обычную версию, так иасинхронная версия

async Task<int> GetRetirementsAsync(){...}

async Task<Tuple<int, int, int, int>> CheckStatusAsync()
{
     ...
     int retired = await GetRetirementsAsync();
     return new Tuple...
}

async Task GetCheckStatusAsync()
{
    var tuple = await CheckStatusAsync();

    // process output:
    LblOut.Text = tuple.Item1.ToString();
    LblStage.Text = tuple.Item2.ToString();
    LblRetired.Text = tuple.Item3.ToString();
    LblStop.Text = tuple.Item4.ToString();
}

Возможное улучшение производительности

Причина, по которой вы хотите использовать GetRetirementsAsync вместо не асинхронного GetRetirements, заключается в том, что вы ожидаете, что где-то глубоко внутри процессабездействовать в ожидании результатов другого процесса, например, при запросе базы данных, чтении файла или получении данных из Интернета.

Вместо ожидания в режиме ожидания вы можете использовать async await для выполнения других задач, пока вам действительно не понадобитсярезультаты из базы данных.

Вы делаете это, запуская задачу, не дожидаясь.Поток не будет бездействовать в ожидании базы данных, но продолжит обрабатывать ваши операторы до тех пор, пока вам не понадобится результат и не дождаться выполнения задачи.

private async Task<Tuple<int, int, int, int>> CheckStatus()
{
    // Get the retirements, do not await yet.
    Task<int> taskGetRetirements = GetRetirementsAsync();

    // instead of waiting idly, your thread is free to do the following:
    int out = 0;
    int stage = 0;
    int retired = 0;
    int stop = 0;
    for (int i = 0; i < Dgv.Rows.Count; i++)
    {
        ...
    }

    // now you need the retirements; await for the task to finish
    int retired = await taskGetRetirements;
    stage = stage - retired;
    return new Tuple<int, int, int,int>(out, stage, retired, stop);
}
...