>我正在使用带有 C# 的 .NET 4.0 任务并行库(我第一次使用 TPL)
我有一个任务 A,我想在启动一堆其他任务(B、C、D 等)之前运行完成。因此,我想创建任务 B、C、D 等作为任务 A 的延续。但是,我想将一个"状态"对象传递给任务 B,将另一个状态对象传递给任务 C,依此类推。
我可以通过简单地使用采用状态对象的 Task 构造函数重载将状态对象传递给任务 A,例如 http://msdn.microsoft.com/en-us/library/dd783035.aspx 描述此 Task 构造函数重载:
Task(Action<Object>, Object, CancellationToken)
这工作正常,第二个参数是我的"状态"对象。
我想创建一个延续任务,例如为任务 B:
Task taskB = taskA.ContinueWith(/* args here*/)
但是,我看不到 ContinueWith() 重载(见 http://msdn.microsoft.com/en-us/library/dd235663.aspx),它允许我将"状态"对象传递给延续任务。如何做到这一点?
笔记:
- 在创建任务 A 时,我没有可用的任务 B 的"状态"对象
- 任务 B 的"状态"对象不是任务 A 的输出(返回值)
对于某些上下文,我正在做的是在几个循环中创建任务B,taskC等,因此我使用状态对象将循环变量的值传递给taskB,taskC等,以避免总是以任务中循环变量的最终值结束的问题(闭包问题)。
最简单的方法可能是简单地在你传递到ContinueWith
Func<Task, TResult>
中捕获它。例如:
object taskBState = GetStateHere();
Task taskB = taskA.ContinueWith(task => RealContinuation(task, taskBState));
就我个人而言,我发现捕获这样的状态比无论如何都传递状态更容易。
你不能。他们希望你使用闭包的力量。只需在循环中定义一个附加变量即可捕获该闭包的当前值。请参阅Jon Skeet的答案,了解有关捕获和关闭的更多详细信息。
更新:或者乔恩·斯基特可以打败我,直接回答你的问题,说完全相同的话。 :)
对于将来的读者,至少在 .NET 4.7 中,ContinueWith()
函数具有允许传递state
参数的重载:
public System.Threading.Tasks.Task ContinueWith(
Action<System.Threading.Tasks.Task,object> continuationAction, object state,
System.Threading.CancellationToken cancellationToken,
System.Threading.Tasks.TaskContinuationOptions continuationOptions,
System.Threading.Tasks.TaskScheduler scheduler);
有关更多详细信息,请参阅此 MSDN 文章。