为什么PauseToken会破坏任务?

问题描述 投票:3回答:2

我想了解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;
}

编辑:

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);
c# wpf async-await
2个回答
5
投票

代码的问题在于,当调用的方法返回时,StartNew()创建的任务被认为是完整的。当然,它是一个async方法与await,该方法返回第一个await执行不完整的任务。

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

没有一个可靠地再现您的问题的好的Minimal, Complete, and Verifiable code example,就不可能确定什么会修复您的程序。但是,我认为最重要的是停止尝试将阻止代码与异步代码混合使用。相反,只需将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);
    }
}

2
投票

我需要使用Task.Run()而不是Task.Factory.StartNew()

Task.Run与Task.Factory.StartNew是here

感谢VladD

© www.soinside.com 2019 - 2024. All rights reserved.