14

问题

这可能是我错过的简单事情。

假设我这样做(在loveley VB中):

Dim t1 As New Task(Sub() Debug.WriteLine("t1"))
Dim t2 As Task = t1.ContinueWith(Sub() Debug.WriteLine("t2"))
Dim t3 As Task = t1.ContinueWith(Sub() Debug.WriteLine("t3"))
t1.Start()

注意 t1.ContinueWith 被使用了两次。这些任务的首选执行顺序是什么?对我来说,要么是随机的,要么是错误的。

为什么?

我想这样做的原因...

  1. 创建任务抓取和返回数据
  2. 随后是“整理”上TaskScheduler.FromCurrentSynchronizationContext()(UI 线程)上的 UI 的任务
  3. 通过将数据转换为长报告来遵循原始数据抓取任务(需要很长时间)
  4. 返回 UI 线程,将该报表分配给预览控件
  5. 清理(​​摆脱我的进度动画等)

由于第 4 步是可选的,这一点变得更加复杂。

在这一切中,我的任务正在向后弯曲以设置成员属性,以便 UI 和任务可以很好地发挥作用。也许我应该完全放弃任务结果,只坚持同步我的成员变量。毕竟它们都只分配一次。

谢谢,汤姆

4

3 回答 3

12

任务以 LIFO 顺序执行,以获得更好的内存局部性。如果您使用不同的调度程序或者 MS 决定“修复”原始调度程序,这当然可以更改。我不认为你应该依赖这种行为。相反,您可以展开任务以在完成前一个任务后继续处理它。否则你在等待错误的事情。更多信息可以在这里找到:http: //msdn.microsoft.com/en-us/library/ee795275.aspx

于 2010-11-19T16:41:56.647 回答
5

如果要强制执行 t2 和 t3 之间的顺序,为什么不直接更改 is 以使 t3 从 t2 而不是 t1 继续?

Dim t1 As New Task(Sub() Debug.WriteLine("t1"))
Dim t2 As Task = t1.ContinueWith(Sub() Debug.WriteLine("t2"))
Dim t3 As Task = t2.ContinueWith(Sub() Debug.WriteLine("t3"))
t1.Start()

如果 t2 和 t3 长时间运行,它们将按照您编写的方式并行执行。

无需创建自定义任务计划程序来更改此行为。

于 2010-11-25T01:36:09.107 回答
4

根据您对 Ian Mercer 回答的评论,我会建议类似

Task t1 = new Task((_)=>Console.WriteLine("t1"));
Task tn = secondTaskCondition ? t1.ContinueWith((_)=>Console.WriteLine("t2")) : t1;
Task t3 = tn.ContinueWith((_)=>Console.WriteLine("t3"));
t1.Start();

这为您提供了确定性的执行,并且仍然允许您使用可选单元来组合您的工作流程。

于 2013-10-17T20:41:26.167 回答