为什么PauseToken会破坏任务?

Kir*_*ill 3 c# wpf async-await

我想了解一下Microsoft.VisualStudio.Workspace.PauseToken.

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

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

两个问题:

  1. 为什么会这样?
  2. 我该如何解决?

我想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;
}
Run Code Online (Sandbox Code Playgroud)

编辑:

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);
Run Code Online (Sandbox Code Playgroud)

Pet*_*iho 5

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

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

如果没有可靠地重现问题的良好的Minimal,Complete和Verifiable代码示例,则无法确定将修复程序的内容.但是,我认为最重要的是停止尝试将阻止代码与异步代码混合使用.相反,只需将您调用的匿名方法StartNew()纳入其自己的命名方法,使其正确异步,并直接调用它.

例如:

private async Task DoDoneAsync()
{
    FlagCommandDone = true;

    try
    {
        await DoDoneLoopAsync();
    }
    catch (Exception e)
    {
        isError = true;
        message = e.Message;
    }

    if (!isError) message = task.IsCompleted ? "Completed" : "Canceled";

    MessageBox.Show(message);

    FlagCommandDone = false;
}

private async Task DoDoneLoopAsync()
{
    double i = 0;
    while (i < 3)
    {
        i++;
        await PauseToken.WaitWhilePausedAsync();
        await Task.Delay(5000);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 嗯......我不明白一点.为什么DoDoneLoopAsync有效?如果等待PauseToken.WaitWhilePausedAsync将被复用,则意味着整个方法将被复用,因为将执行第一个await.我哪里错了? (2认同)