Почему PauseToken прерывает Task?

196
25 декабря 2017, 10:15

Пытаюсь разобраться с 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;
}
Answer 1

Проблема в Task.Factory.StartNew.

Этот метод запускает обыкновенные функции как Task, но для асинхронных он делает не то, что вы ожидаете. Используйте Task.Run вместо него.

Давайте вспомним, как выполняются асинхронные функции. Ваш async-делегат с точки зрения внешнего кода не выполняется до конца, а завершается с первым внутренним await'ом, возвращая Task (который, в свою очередь, завершится с окончанием выполнения всей асинхронной функции). Следовательно, ваш task является не заданием выполнения всей асинхронной функции, а лишь заданием получения на неё Task'а! Действительно, сигнатура вашего async-делегата есть Task f(), а сигнатура функции, возвращённой из Task.Factory.StartNewTask<Task> f().

Task.Run обрабатывает эту ситуацию более ожидаемым образом: он получает Task<Task>, и делает внутри await, таким образом, вы дожидаетесь «внутреннего» таска, представляющего собой ваш асинхронный делегат.

Литература: PFX team, Task.Run vs Task.Factory.StartNew (кажется, русский перевод тут).

READ ALSO
checkbox запоминает при возврате на страницу

checkbox запоминает при возврате на страницу

Имеется данный код суть такая что нельзя выбирать больше 5 чекбоксов(у меня их 10)Все работает но проблема в том что когда человек возвращаться...

268
Ajax - не конвертирует в объект json с сервера

Ajax - не конвертирует в объект json с сервера

Вечер добрыйЕсть кнопка в хтмл при клике на нее срабатывает этот скрипт:

257