2012-11-08 155 views
9

我在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,有没有办法能够可靠地等待包含await s到完成任务?

+4

我想你应该直接调用'Task.Delay'而不是'await'关键字。 –

+2

你会注意到'_'实际上是一个'Task ',它完全支持Justin在说什么...... –

+0

事实上,使用Task.Delay(6)会产生预期的结果,但不会等待6秒。我认为删除整条线几乎是一样的。 –

回答

10

当你传递一个async委托Task.Factory.StartNew,返回Task仅代表委托(直到一次await件事情是不是已经完成)的第一部分。

但是,如果您将async委托人传递给新的Task.Run方法(由于此原因而包含此方法),则返回的Task表示整个委托人。所以你可以像你期望的那样使用ContinueWith。 (尽管await通常比ContinueWith更好)。

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

+0

链接的帖子说得很清楚。谢谢!! –

4

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

+0

我认为你是对的 - 等待标记目前的任务已完成。虽然它不是(至少不是从语义的角度来看)。正如await是今天所有软件的基本组成部分,这意味着永远不会依赖ContinueWith。你不觉得,这是一个错误? –

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

所以不要忘记“异步()”!

+0

他的代码有'异步',他的问题是他正在使用'TaskFactory',它没有一个超载,它接受'Task.Run'具有的'Func '或'Func >'。 –

相关问题