0

示例代码:

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...} 之前卡住。

4

5 回答 5

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 (); 
    }
} 
于 2012-09-24T12:12:28.580 回答
2

这是另一种方法,也许使用像AutoResetEvent这样的EventWaitHandle,所以线程 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 ();
    }
}
于 2012-09-24T13:24:27.150 回答
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 ();
    }
}
于 2012-09-24T12:11:48.940 回答
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();
}
于 2012-09-24T12:13:20.287 回答
1

看看Lazy 类。这可确保自动处理对具体对象的多线程访问。

您可以通过在构造函数中定义LazyThreadSafetyMode来控制如何处理同时访问。

于 2012-09-24T12:20:20.273 回答