2016-11-05 8 views
0

iはbelowsのようにいくつかのコードがあります。なぜmonitor.exitは別の作業で動作しないのですか?

static void Main(string[] args) 
    { 
     var async = new object(); 

     Monitor.Enter(async); 

     Task.Run(async() => 
     { 
      await Task.Delay(5000); 
      Monitor.Exit(async); 
     }); 

     Monitor.Wait(async); 
     Monitor.Exit(async); 
    } 

をそれは永遠にMonitor.Waitでブロックします。私はsemaphore.butを使ってこの問題を解決することができますが、なぜそれが起こり、mutex、spinlock、barrier.thksについては知りたいのですか?

+3

"しかし、それはいつまでもMonitor.Waitでブロックされます" - うん、そうではなく、何も 'Monitor.Pulse'を呼んでいない。なぜこれがうまくいくと思ったのかは明らかではありませんが、モニターを所有していないスレッドで 'Monitor.Exit'を呼び出すと例外がスローされます。また、特にasync/awaitを使っているメソッドでは、変数asyncを命名することを強くお勧めします。 –

+0

あなたは正確に何をしようとしていますか? –

+0

http://stackoverflow.com/a/21404261/6527049 –

答えて

2

Monitorは、スレッド親和性を有する。別のスレッドから終了することはできません。

しかし、とにかくここで何をしようとしているのかは不明です。あなたはすでに別の非同期メソッドを呼び出す非同期メソッドになっています。 awaitを使用してください。ちょうどコンソールアプリケーションでawaitを正しく使用できるように同期コンテキストを設定してください。デッドロックを心配していない場合は、Task.Waitを使用してください。

Monitor.Waitについては、あなたが思っていることはしません。待機は、モニターのためではなく、信号のためのものです。例:

static readonly object syncObject = new object(); 

void Thread1() 
{ 
    lock (syncObject) Monitor.Wait(syncObject); 
} 

void Thread2() 
{ 
    lock (syncObject) Monitor.Pulse(syncObject); 
} 

このシナリオでは、どちらの方法も別のスレッドで実行されます。 Thread1が最初に実行されると、ロックを取り、シグナルを待って(シグナルが出るまでロックを終了します)、シグナルが与えられた後にロックを再獲得します。 Thread1Monitor.Pulseメソッドを使用して信号を提供します。どちらの場合も、ロックは単一のスレッドで行われ、同じスレッドで終了されることに注意してください。

このメカニズムは、使い方が非常に簡単ではなく、やや遅いので、あまり見ないようにしています。

また、Task.Runで使用されるスレッドはあなたのものではありません。スレッドプールスレッドでブロッキングコードを使用することは、通常は望ましくありません。作成するトレードオフを理解していることを確認してください。さらに重要なのは、タスクにはスレッドアフィニティがないからです。つまり、モニタのようなスレッドアファインの同期プリミティブを使用するのはむしろ冒険的です:)あなたの場合、外部ではなくTask.Runの内部でロックを取ったとしても、 awaitの後に別のスレッドを取得した可能性があるため、Monitor.Exitが失敗する可能性があります。

マルチスレッドの最も難しい部分は、うまく動作しないということではなく、ほとんどの場合ほとんど動作しないという醜い傾向があります。実際にはいつも、あなたに気をつけてください)。テストでは、マルチスレッドのコードが実際にどのように動作するかについて、十分に自信を持てるほど十分ではありません。あなたが得るのは、バグを再現するのがほとんど不可能で、ほとんど不可能です。あなたはここでラッキーです - あなたのコードは確実に失敗します。それは確かにほとんどのマルチスレッドの問題ではありません:)

Joe Albahari's introduction to threadingは、あらゆる種類のマルチスレッドプログラミングの大きな助けです。私は強くそれを少なくとも1回読むことを強くお勧めします。将来の参照のためにブックマークに残してください:)

関連する問題