为什么这个对象是空的
本文关键字:对象 为什么 | 更新日期: 2023-09-27 18:15:02
我有一个静态字段的类,像这样
public class MyClass
{
public static Guid MyField1 { get; set; }
}
那么我有一个这样的方法。
public void MyMethod()
{
MyClass.MyField1 = Guid.NewID();
Task.Factory.StartNew( () => { MyAnotherMethod(MyClass.MyField1);}) ;
}
问题是,当我点击调用缅甸方法(),我得到一个异常,'MyClass. 'MyField1'抛出了类型为'System.NullReferenceException'的异常。然而,如果我用下面替换Task.Factory.StartNew调用,它工作得很好。
ThreadPool.QueueUserWorkItem(MyAnotherMethod, MyClass.MyField1);
任何想法?
我认为这是一个线程/缓存问题。在线程1中,您将11赋值给属性,但该值在缓存中,线程2不知道(例如,它正在查看RAM)。为了避免这个问题,你可以使用锁,或者在变量上指定volatile关键字。
试试这个:
private static volatile int myField1;
public static int MyField1 { get { return myField1; } set { myField1 = value; } }
并行调用方法的两个版本之间存在差异。在Task版本中,将Task代码定义为不带参数的lambda函数,并在其中执行代码
MyAnotherMethod(MyClass.MyField1);
在ThreadPool版本中,您将传递给ThreadPool的任务定义为要用初始参数MyClass.MyField1
启动的方法MyAnotherMethod
的代码。
如果在调用ThreadPool.QueueUserWorkItem
之后,您以某种方式修改了MyField1
,则任务启动将不会受到任何影响,因为MyField1已经在堆栈上复制并且任务开始执行。
另一方面,如果在调用StartNew
之后修改MyField1,则可能在Task方法内部的方法调用发生之前发生数据争用,并且Task内部的方法以不同的MyField1值执行。