重要な領域を持つアプリケーションを作成しています。AutoResetEvent.WaitOne()が原因でデッドロックが発生する
私は相互排除を実現するためにAutoResetEventを使用することにしました。 は、ここで私は、クリックイベントを呼び出しますButton_Click()
方法
それが正常に動作ボタンを持っているコード
public class MyViewModel
{
private AutoResetEvent lock = new AutoResetEvent(true);
private aync Task CriticalRegion()
{
Dosomething();
}
public async Task Button_Click()
{
Debug.WriteLine("Entering Button_Click");
lock.WaitOne();
try
{
await CriticalRegion();
}
finally
{
lock.Set();
Debug.WriteLine("Leaving Button_Click");
}
}
}
です。しかし、Button_Click()
への最初の呼び出しが完了する前に、別の時間ボタンをクリックするのに十分速ければ、アプリケーション全体が応答を停止します。デバッグウィンドウで
私は、メソッドが完了したことがないように、この
Entering Button_Click
Entering Button_Click
のようなものが見える見つけます。
私は少し苦労し、私はこの場合lock.WaitOne();
if (!sync.WaitOne(TimeSpan.FromSeconds(1)))
{
return;
}
を変更した場合、私のアプリは、デッドロックを回避することができますが、それは動作しますなぜ私にはわからないことがわかります。
私は自分のOSコースのIPCと、C#のasync
とawait
のパターンしか知りません。私は.NETの世界のスレッドに慣れていません。
実際に何が舞台裏で起こっているのか本当に理解したいです。任意のreplysため 感謝;)あなたは後WaitOne()
コールを除いて行うように見えることはありませんAutoResetEvent.Set()
を呼び出すまで
投稿されたスニペットはデッドロックのデモンストレーションには不十分です。しかし、間違っていることは明らかです。クラス名に少し集中してください。それはオートリセット*イベント*です。イベントはシグナリングに使用され、「重要領域」には相互排除が必要です。これはmutexを必要とします。最も簡単にはC#で 'lock'キーワードを使って行います。UIスレッドのロックを使用することは正式には違法であり、事実上、デッドロックを引き起こす可能性は非常に高くなります。 –