示例代码:
MyObject myObject = new MyObject ();
public void FunA () // accessed from thread 1 (when user click a button)
{
myObject = null;
// do some stuff
myObject = new MyObject ( someNewValues );
}
public void FunB () // accessed from thread 2 (calling using timer or smth.)
{
int x = myObject.ReadX ();
}
在大多数情况下,它可以正常工作,但是当FunA将myObject设为null并且同时FunB将访问它时,应用程序将崩溃。
问题:怎么做,当线程1访问FunA时,线程2无法进入FunB?
更新:之前我尝试过锁,但问题是FunB正在调用事件到线程1(GUI)(guiForm.Invoke),线程1将在FunA {lock ...}之前停留。
答案 0 :(得分:2)
只需对锁定对象发出锁定,如下所示:
static object lockObject = new Object();
MyObject myObject = new MyObject ();
public void FunA () // accessed from thread 1 (when user click a button)
{
lock (lockObject)
{
myObject = null;
// do some stuff
myObject = new MyObject ( someNewValues );
}
}
public void FunB () // accessed from thread 2 (calling using timer or smth.)
{
lock (lockObject)
{
int x = myObject.ReadX ();
}
}
答案 1 :(得分:2)
这是一种替代方法,可能使用像EventWaitHandle这样的AutoResetEvent,因此线程2会阻塞,直到线程1设置了线程同步对象。
示例代码:
MyObject myObject = new MyObject ();
private static EventWaitHandle WaitHandle_m = new AutoResetEvent(false);
public void FunA () // accessed from thread 1 (when user click a button)
{
myObject = null;
// do some stuff
myObject = new MyObject ( someNewValues );
WaitHandle_m.Set();
}
public void FunB () // accessed from thread 2 (calling using timer or smth.)
{
if (!WaitHandle_m.WaitOne(TimeSpan.FromMinutes(10)))
{
// whoops.
}
else
{
int x = myObject.ReadX ();
}
}
答案 2 :(得分:1)
您可以锁定myObject
,以便只有当前线程才能使用它。
public void FunA () // accessed from thread 1 (when user click a button)
{
lock(myObject)
{
myObject = null;
// do some stuff
myObject = new MyObject ( someNewValues );
}
}
这会阻止FunB
在锁定释放之前访问myObject
。
<强>更新强>
正如评论中指出的那样,修改你锁定的对象可能不是一个好主意。在这种情况下,您可以简单地拥有一个锁定的对象和一个您修改的对象:
var lockObj = new object();
var myObject = new MyObject();
public void FunA () // accessed from thread 1 (when user click a button)
{
lock(lockObj)
{
myObject = null;
// do some stuff
myObject = new MyObject ( someNewValues );
}
}
public void FunB () // accessed from thread 2 (calling using timer or smth.)
{
lock(lockObj)
{
int x = myObject.ReadX ();
}
}
答案 3 :(得分:1)
这是一个经典的同步问题。互斥是有用的。查看MSDN中的示例。 http://msdn.microsoft.com/en-us/library/system.threading.mutex.aspx
应该是这样的
MyObject myObject = new MyObject ();
Mutex mutex = new Mutex();
public void FunA ()
{
mutex.WaitOne();
myObject = null;
// do some stuff
myObject = new MyObject ( someNewValues );
mutex.ReleaseMutex();
}
public void FunB ()
{
mutex.WaitOne();
int x = myObject.ReadX ();
mutex.ReleaseMutex();
}
答案 4 :(得分:1)
查看Lazy class。这样可以确保自动处理对具体对象的多线程访问。
您可以通过在构造函数中定义LazyThreadSafetyMode来控制如何处理同步访问。