await Task.Run на самом деле не ждет - PullRequest
0 голосов
/ 23 января 2019

Я пытаюсь обойти асинхронное ожидание, однако я написал небольшой тест и не могу понять, какие результаты я получаю.

Рассмотрим следующий код (приложение WPF, внутри MainWindow):

private async void Button_Click(object sender, RoutedEventArgs e)
{
    Stopwatch l_Stopwatch = new Stopwatch();

    Debug.WriteLine("Entering Button_Click...");

    l_Stopwatch.Start();

    await DoSomethingAsync();

    l_Stopwatch.Stop();

    Debug.WriteLine("DoSomethingAsync completed in {0}", l_Stopwatch.ElapsedMilliseconds);

    l_Stopwatch.Restart();

    await DoSomethingElseAsync();

    l_Stopwatch.Stop();

    Debug.WriteLine("DoSomethingElseAsync completed in {0}", l_Stopwatch.ElapsedMilliseconds);
}

private async Task DoSomethingAsync()
{
    Debug.WriteLine("Doing something Async");

    await Task.Delay(5000);

}

private async Task DoSomethingElseAsync()
{
    await Task.Run((Action)(async () => { 
        Debug.WriteLine("Doing something else Async");

        await Task.Delay(5000);
    }));
}

Я бы ожидал, что DoSomethingElseAsync будет ждать ~ 5000 мс, прежде чем продолжить, однако я продолжаю получать следующее

Entering Button_Click...
Doing something Async
DoSomethingAsync completed in 5005
Doing something else Async
DoSomethingElseAsync completed in 3

Так что на данный момент я думаю, что есть нечто фундаментальное, что я не понимаю пути асинхронного ожидания ...

Может ли кто-нибудь пролить свет?

1 Ответ

0 голосов
/ 23 января 2019

Проблема здесь:

await Task.Run((Action)(async () => { 
    Debug.WriteLine("Doing something else Async");

    await Task.Delay(5000);
}));

Вы приводите к Action делегату, который ничего не возвращает и не может ожидать (нет Task, чтобы ждать, потому что Action возвращает void).

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

await Task.Run(async () => { 
    Debug.WriteLine("Doing something else Async");

    await Task.Delay(5000);
});

ИЛИ

, который вы можете привести к Func<Task> делегату, которыйвозвращает Task, который можно ожидать:

await Task.Run((Func<Task>)(async () => { 
    Debug.WriteLine("Doing something else Async");

    await Task.Delay(5000);
}));

Дополнительная информация:

Если вы увидите сгенерированный компилятором код ( SharpLab ), вы получитеполучить различия:

  • Когда вы приводите к Action, компилятор создает AsyncVoidMethodBuilder
  • Когда вы приводите к Func<Task> или вообще не приводите к компилятору AsyncTaskMethodBuilder
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...