2012-02-17 12 views
3

WaitOne()を呼び出す前にC#System.Threading.AutoResetEventまたは System.Threading.ManualResetEventのブロッキング状態をチェックすることはできますか?C#でAutoResetEventまたはManualResetEventのブロック状態をチェックする方法は?

+0

反射を使用します。あなたの実際の問題は何ですか? –

+0

私は特別なハードウェアと話すUDPクライアントを開発しています。私はコミュニケーションを同期させるためにブロックコードを実装しなければなりませんでした。私はWaitOne()の前にブレークポイントを置くことができないので、物事は速く走らなければなりません。私は4つのAutoResetEventsを持っています。コミュニケーションのブロックが私が魔女1で知りたかった時。私は、コンソールへのライティングは、ライティングにどこの時間がかかるかを示してくれることを知っています。そのような重要な環境では、時間を無駄にすることはできません。 – Patrik

答えて

4

EventWaitHandleには「ブロッキング状態」がありません。それは設定され、リセットされます。そして、いいえ、WaitOne()を呼び出す以外の方法で確認することはできません。

ブロッキングを避けるために、time-out引数に0を渡すことができます。これはWaitOne()呼び出しが復帰した後のイベントの状態について何も言わないので、しばしば非常に悪い考えです。その後、ナノ秒を変更した可能性があります。これは "スレッドレース"と呼ばれる非常に厄介な種類のバグを引き起こします。 Heisenbug。

+0

+1、完全にあなたに同意する! –

+0

私はEventWaithandleがブロッキング状態ではないことを知っていますが、通知されていない場合は現在のスレッドの実行をブロックしています。私はスレッド内で動作するループ中に4つのEventWaitHandlesを持っています。それらのうちのいくつかは条件付きでスレッドをブロックする必要があります。私は、これらの4つのハンドルのどれがブロックされているかを他のイベントから知りたいと思っていました。これらの情報を取得するには、ハンドルにリンクされたブール変数を追加する必要があることがわかります。 – Patrik

1

MSDNによると、タイムアウトは0で使用

public virtual bool WaitOne(
    TimeSpan timeout 
) 

それはすぐにWaitHandleの状態を返します。

+0

これに言及します。 AutoResetEventのWaitOne(0)がリセットされる可能性があります。 WaitOneがシグナルされた場合は、WaitOneの後にSetを使用する必要があります。しかし、私は競争条件についてHansに同意しなければならない。あなたがWaitOneを呼び出した複数のスレッドがある場合、これは厄介なバグを引き起こす可能性があります。 ManualResetEventでは問題ありません。 – BlueM

0

私は同じ質問をしました。デモアプリケーションを作成するだけです。あなただけのこの操作を行うと、そのインスタンスのブロッキング状態を確認する必要が任意の時点で

Module Module1 

Dim ewh As Threading.EventWaitHandle 

Sub Main() 
    ewh = New Threading.EventWaitHandle(False, Threading.EventResetMode.ManualReset) 
    ' Do other work. 
End Sub 

Sub checkBlockStatus() 

    ewh.WaitOne() 

End Sub 

Function isEwhBlocked() As Boolean 

    Dim testEwhBlock As New Threading.Thread(AddressOf checkBlockStatus) 
    testEwhBlock.Start() 
    Threading.Thread.Sleep(1000) 
    If testEwhBlock.ThreadState <> Threading.ThreadState.Stopped Then 
    ' It's OK to use abort here because I don't care what happens to the thread. 
    testEwhBlock.Abort() 
    Return True 
    Else 
    Return False 
    End If 
    testEwhBlock = Nothing 

End Function 
End Module 

:(。EventWaitHandleへの初心者は)

これは私が(VB.NETで)問題を解決する方法です。

if (isEwhBlocked()) Then 
    ' This means the block is on. 
else 
    ' No block. 
End If 

だから、いいえ、あなたは本当にWAITONE()を呼び出す前にブロックされているかを把握することはできませんが、あなたのメインスレッドを押収するのを防ぐ非同期方法でそれを実行することができます。もしそれが待たなければならないのであれば、おそらく睡眠の値をかなり下げることもできます。

明らかに、複数のブロックをチェックする必要がある場合、関数は少し複雑になります(またはそれらをさらに作成する必要があります)が、これは基本原理を示しています。私はこれをAutoResetとしてもテストしましたが、それはうまく動作しません。ハンドラが自動設定されているので、ブロックをチェックするメソッドを呼び出すと、他のスレッドをリセットしてブロックします。したがって、ManualResetで実行できる場合、これはあなたのために働くことができます。

関連する問題