.Continue 在任务完成前开始

Posted

技术标签:

【中文标题】.Continue 在任务完成前开始【英文标题】:.Continue starts before task is completed 【发布时间】:2012-10-28 10:47:13 【问题描述】:

我在 C#、VS2012、WPF 4.5 中有以下代码。 我的期望是,.ContinueWith 将在任务完全完成后执行(这是延续的全部目的,不是吗?)。

这应该导致finalResult 中的值为 2。

int myTestInt = 0;

Task task = Task.Factory.StartNew(async () =>

   myTestInt = 1;
   await Task.Delay(TimeSpan.FromSeconds(6));
   myTestInt = 2;

).ContinueWith(_ =>
   
      int finalResult = myTestInt;
   );

事实上,finalResult 被赋值为 1。所以看起来延续已经在await 语句上开始了。

这是预期的行为吗?我在这里错过了什么吗?我不能依靠ContinueWith在任务完成后开始吗?

更新:

贾斯汀的回答启发了我检查以下内容:

int myTestInt = 0;
Task task=Task.Factory.StartNew(async () =>

   myTestInt = 1;
   await Task.Delay(TimeSpan.FromSeconds(6));
   myTestInt = 2;
);

task.Wait();
int result2 = myTestInt;

finalResult 仍然设置为 1。有没有办法可靠地等待包含 awaits 的任务完成?

【问题讨论】:

我认为你应该直接调用Task.Delay——而不是使用await关键字。 你会注意到_实际上是一个Task<Task>,完全支持Justin所说的...... 其实使用Task.Delay(6)会产生预期的结果,但不会等待6秒。我认为删除整行几乎是一样的。 【参考方案1】:

当您将 async 委托传递给 Task.Factory.StartNew 时,返回的 Task 仅代表该委托的第一部分(直到它 awaits 尚未完成的内容)。

但是,如果您将 async 委托传递给新的 Task.Run 方法(为此包含该方法),则返回的 Task 代表整个委托。因此,您可以按预期使用ContinueWith。 (虽然await 通常比ContinueWith 更好)。

有关StartNewRun 的更多信息,请参阅Stephen Toub's post on the topic。

【讨论】:

【参考方案2】:

await 将立即将控制权返回给调用函数,在本例中是您的任务的 StartNew。这意味着任务将完成并执行 ContinueWith。 如果您确实希望在 ContinueWith 之前完成任务,则不要等待 Task.Delay。

【讨论】:

我认为你是对的 - await 将当前任务标记为已完成。虽然不是(至少从语义的角度来看不是)。由于 await 是当今所有软件的基本构建块,这意味着永远不要再依赖 ContinueWith。你不认为这是一个错误吗?【参考方案3】:

我在 MSDN 中看到了这个::-)

public async  void button1_Click(object sender, EventArgs e)

    pictureBox1.Image = await Task.Run(async() =>
    
        using(Bitmap bmp1 = await DownloadFirstImageAsync())
        using(Bitmap bmp2 = await DownloadSecondImageAsync())
        return Mashup(bmp1, bmp2);
    );

所以不要忘记 "async()" !!!

【讨论】:

他的代码有async 他的问题是他正在使用TaskFactory,它没有接受Func<Task>Func<Task<T>> 的重载,而Task.Run 确实有。

以上是关于.Continue 在任务完成前开始的主要内容,如果未能解决你的问题,请参考以下文章

Python入门教程第20篇 continue语句

break 和continue的两种用法

如何再 freemarker中 的list 循环中 实现 continue的功能?

python学习之break和continue在for循环中的使用(案例:打印出10以内的偶数,并且只要前三个偶数)

for循环及break和continue的区别

控制流之continue