为什么PauseToken会破坏任务?

时间:2017-12-24 06:52:49

标签: c# wpf async-await

我试图了解Microsoft.VisualStudio.Workspace.PauseToken

当我调用PauseTokenSource.Pause()时,方法暂停,任务完成,我可以看到"已完成"消息。

之后我打电话给PauseTokenSource.Resume(),任务继续进行。 但是当流程结束时我没有任何消息。

两个问题:

  1. 为什么会这样?
  2. 我该如何解决?
  3. 我希望PauseToken在工作期间不要破坏任务。暂停后我不想收到消息。我想在过程的真正结束时得到消息。

    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;
    }
    

    修改

    task = Task.Factory.StartNew(async () =>
    {
        double i = 0;
        while (i < 3)
        {
            i++;
            CurrentStatus = i.ToString();
            var a = (int)(double)((i / 3.0) * 100.0);
            MessageBox.Show(PauseToken.IsPaused.ToString());
            await PauseToken.WaitWhilePausedAsync();
            CancellationToken.ThrowIfCancellationRequested();
            Thread.Sleep(5000);
            CurrentProgress = a;
        }
    }
    , CancellationToken);
    

2 个答案:

答案 0 :(得分:5)

代码的问题在于,当被调用的方法返回时,StartNew()创建的任务被视为完成。当然,它是一个带async的{​​{1}}方法,只要在不完整的任务上执行第一个await,该方法就会返回。

所以,你的await方法实际上是在你认为你开始完成之前完成的。它基本上只等到您的DoDoneAsync()方法到达第一个StartNew()

如果没有一个能够可靠地再现您的问题的好Minimal, Complete, and Verifiable code example,就不可能确定什么会修复您的程序。但是,我认为最重要的是停止尝试将阻止代码与异步代码混合使用。相反,只需将await调用的匿名方法分解为自己的命名方法,使其正确异步,并直接调用它。

例如:

StartNew()

答案 1 :(得分:2)

我需要使用Task.Run()代替Task.Factory.StartNew()

Task.Run vs Task.Factory.StartNew是here

感谢VladD