我有一个像这样的静态字段的类
public class MyClass
{
public static Guid MyField1 { get; set; }
}
然后我有这样的方法。
public void MyMethod()
{
MyClass.MyField1 = Guid.NewID();
Task.Factory.StartNew( () => { MyAnotherMethod(MyClass.MyField1);}) ;
}
问题是当我点击对MyAnotherMethod()的调用时,我得到一个异常,'MyClass.MyField1'抛出了类型'System.NullReferenceException'的异常。但是,如果我用下面替换Task.Factory.StartNew调用,它可以正常工作。
ThreadPool.QueueUserWorkItem(MyAnotherMethod, MyClass.MyField1);
有什么想法吗?
答案 0 :(得分:0)
我认为这是一个线程/缓存问题。在线程1中,为属性分配11,但值在缓存中,而线程2不知道(例如,它正在查看RAM)。要避免此问题,您可以使用锁定,也可以在变量上指定volatile keyword。
试试这个:
private static volatile int myField1;
public static int MyField1 { get { return myField1; } set { myField1 = value; } }
答案 1 :(得分:0)
并行调用该方法的两个版本之间存在差异。在任务版本中,您将任务代码定义为没有参数的lambda函数,并在内部执行代码
MyAnotherMethod(MyClass.MyField1);
在ThreadPool版本中,您将传递给ThreadPool的任务定义为使用初始参数MyAnotherMethod
启动的方法MyClass.MyField1
的代码。
如果在调用ThreadPool.QueueUserWorkItem
后以某种方式修改MyField1
,则启动的任务无论如何都不会受到影响,因为MyField1已经被复制到堆栈上并且任务开始执行。
另一方面,如果在调用StartNew
之后修改MyField1,则可能在Task方法内部的方法调用发生之前发生数据争用,并且Task内部的方法执行时MyField1的不同值。我希望你能理解我在这里想说的话......