#c_sharp #wpf #async
Пытаюсь разобраться с PauseToken (Namespace: Microsoft.VisualStudio.Workspace).
Не могу понять когда вызываю PauseTokenSource.Pause(); PauseToken уходит в паузу
и одновременно завершает task и я получаю сообщение "Completed".
Но при этом если после PauseTokenSource.Pause(); вызвать PauseTokenSource.Resume();,
то task продолжит работать, но по окончании никаких сообщений не будет.
Два вопроса почему так происходит, и как это можно поправить?
public PauseToken PauseToken;
private async Task DoDoneAsync()
{
FlagCommandDone = true;
try
{
task = Task.Factory.StartNew(async () =>
{
double i = 0;
while (i < 3)
{
i++;
await PauseToken.WaitWhilePausedAsync();
Thread.Sleep(5000);
}
}
);
await task;
}
catch (Exception e)
{
isError = true;
message = e.Message;
}
if (!isError) message = task.IsCompleted ? "Completed" : "Canceled";
MessageBox.Show(message);
FlagCommandDone = false;
}
Ответы
Ответ 1
Проблема в Task.Factory.StartNew. Этот метод запускает обыкновенные функции как Task, но для асинхронных он делает не то, что вы ожидаете. Используйте Task.Run вместо него. Давайте вспомним, как выполняются асинхронные функции. Ваш async-делегат с точки зрения внешнего кода не выполняется до конца, а завершается с первым внутренним await'ом, возвращая Task (который, в свою очередь, завершится с окончанием выполнения всей асинхронной функции). Следовательно, ваш task является не заданием выполнения всей асинхронной функции, а лишь заданием получения на неё Task'а! Действительно, сигнатура вашего async-делегата есть Task f(), а сигнатура функции, возвращённой из Task.Factory.StartNew — Taskf(). Task.Run обрабатывает эту ситуацию более ожидаемым образом: он получает Task , и делает внутри await, таким образом, вы дожидаетесь «внутреннего» таска, представляющего собой ваш асинхронный делегат. Литература: PFX team, Task.Run vs Task.Factory.StartNew (кажется, русский перевод тут).
Комментариев нет:
Отправить комментарий