。继续在任务完成之前开始

时间:2012-11-08 08:59:49

标签: c# .net wpf task-parallel-library async-await

我在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来启动吗?

更新

Justin的回答激发了我检查以下内容:

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.是否无法可靠地等待包含await的任务完成?

3 个答案:

答案 0 :(得分:10)

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

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

有关StartNew vs Run的详情,请参阅Stephen Toub's post on the topic

答案 1 :(得分:4)

await将立即将控制权返回给调用函数,在这种情况下,调用函数是您的任务的StartNew。这意味着任务将完成并执行ContinueWith。 如果你真的希望在ContinueWith之前完成任务,那么就不要等待Task.Delay。

答案 2 :(得分:-1)

我在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()”!!!