阻止线程进入方法

时间:2012-09-24 12:09:57

标签: c# multithreading

示例代码:

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 ...}之前停留。

5 个答案:

答案 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来控制如何处理同步访问。