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 を使用して、スレッド1スレッド同期オブジェクトを設定するまでスレッド 2 をブロックします。

コード例:

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

これは典型的な同期の問題です。ミューテックスが役立ちます。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 に答える
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 に答える