动作委托内的任务实例
问题描述:
我的代码中的任务(t
)不能在我的代码中直接在我的代码中使用。我得到以下错误:动作委托内的任务实例
代码:
Task t = Task.Factory.StartNew(() =>
{
MessageBox.Show(t.Id.ToString());
});
现在,如果我做了以下工作:
Task t = null;
t = Task.Factory.StartNew(() =>
{
MessageBox.Show(t.Id.ToString());
});
可能有人请解释为什么是这样的话?
答
C#编译器不知道什么关于Task.Factory.StartNew
。就编译器而言,在调用StartNew
之后,包括t
被分配之前的任何时间,可以在任何时间访问t
。
您的第二个代码片段有竞争条件:如果并发线程上的任务在分配完成之前转到显示消息框,您将看到空引用异常。
试试这个实验:
private static Task Wrapper(Action f) {
var res = Task.Factory.StartNew(f);
Thread.Sleep(1000);
return res;
}
现在用的Wrapper
在你的第二个片段的调用替换Task.Factory.StartNew
直接通话,并观看了程序崩溃。
Task t = null;
t = Wrapper(() => {
MessageBox.Show(t.Id.ToString());
});
答
您必须首先为t分配一个值,以便它获得对Task类型的对象的引用。
在你的第一批代码中,你尝试给t赋一个值并在一个语句中使用它(在那里只有一个分号)。
在第二个示例中,这些是两个单独的语句,因此它将起作用。
这两个片段(在问题中)具有相同的竞争条件。但编译器不知道,错误来自静态分析。 – 2012-07-26 11:22:59
@HenkHolterman是的,它仍然存在。这个想法是为了使比赛条件更加明显。 – dasblinkenlight 2012-07-26 11:23:29
很好的解释,谢谢。那么,在代理中访问我的任务实例有没有安全的方法? – davenewza 2012-07-26 11:24:38