2011-01-27 29 views
0

イベントがトリガーされるのを待たなければなりません。私の最初の解決策は、AutoResetEventWaitOne()を使用することでしたが、イベントは常にが待機タイムアウトが終了した直後にトリガーされました。そこで私は下のアプローチに戻りましたが、私はまだ同じ問題を抱えています。タイムアウトが終了してから2〜3秒後に、タイムアウトが何であってもイベントが発生します。タイムアウトが終了した後にイベントがトリガーされる

private void OnResponseArrived(object sender, ResponseEventArgs args) 
{ 
    _delayedResponse = args.VerificationResponse; 
} 

イベント自体は、上記の関数を呼び出す他の関数からトリガされる:ここ

_wait = true; 
_delayedResponse = null; 

var thread = new Thread(delegate 
{ 
     while (_wait) 
     { 
      Thread.Sleep(500); 
      if (_delayedResponse != null) 
       return; 
     } 
}); 

thread.Start(); 
var received = thread.Join(_responseTimeout); 
_wait = false; 

if (!received) 
    throw new TimeoutException(
     "Timeout for waiting for response reached."); 

return _delayedResponse; 

イベントハンドラコードです。 基本的には次のようになります。

var result = DoStuff(); // Library function that is responsible for the event 
if (result.Status == Status.Wait) 
    Wait(); // Function above 

誰もがこの問題の原因とどのように私はそれを解決することができますどのような考えを持っていますか?

編集:関連性はなくなりました。 OnResponseArrivedイベントを転送しました。他の解決策が見つからなかったためです。

+2

ここからイベントをトリガーしていますか? –

+0

「タイムアウトに関係なくイベントが発生します」という意味はどうですか? 'ResponseArrived'イベント?このイベントが別のスレッドから起動されたことは確かですか? – Groo

+0

ご意見ありがとうございます。私は質問を更新しました。 – xsl

答えて

2

Thread.Joinはブロッキングコールです。これは、呼び出しているスレッドを他の作業から停止させます。私の推測では、あなたがバックグラウンドスレッドでのイベントをを待っているということですが、あなたのイベントはあなたが実行を掲載コードと同じスレッドで実行されて発生しますコード。

thread.Joinを呼び出すことによって、あなたがしています処理を行うスレッドをブロックします。したがって、あなたのタイムアウトが期限切れになるのを待ってください...あなたの投稿されたコードが完了したら、どちらかの方法が... 次に処理が実際に起こり、ResponseArrivedイベントが発生します。

残りのコードを投稿すると便利ですが、ソリューションの要点はバックグラウンドスレッドで実際の作業(すべてのコードがResponseArrivedイベントを発生させるもの)を実行して余分なスレッドを削除することです投稿したコードからコメントに応答して

EDIT ...

コードのあなたの2枚を同期させるために、あなたはAutoResetEventを使用することができます。あなたは、あなたがそれで終わったらAutoResetEventを処分する必要があります

// create an un-signalled AutoResetEvent 
AutoResetEvent _waitForResponse = new AutoResetEvent(false); 

void YourNewWorkerMethod() 
{ 
    _delayedResponse = null; 
    var result = DoStuff(); 

    // this causes the current thread to wait for the AutoResetEvent to be signalled 
    // ... the parameter is a timeout value in milliseconds 
    if (!_waitForResponse.WaitOne(5000)) 
     throw new TimeOutException(); 

    return _delayedResponse; 
} 


private void OnResponseArrived(object sender, ResponseEventArgs args) 
{ 
    _delayedResponse = args.VerificationResponse; 
    _waitForResponse.Set(); // this signals the waiting thread to continue... 
} 

注:代わりにThread.Sleepとあなたの他のコードを使用しての、このような何かを試してみてください。

+0

私はそれを期待しました。私は自分のコードでDoStuff()関数を制御することはできませんが、Busyの場合はWaitStatusを返すので、スレッドを使用していると仮定しました。イベントが返されたとき、または定義された時間が経過したときに関数を終了します。これを達成するための提案はありますか? – xsl

2

まず、DoStuffがバックグラウンドスレッドで実際に動作することを確認してください。

あなたのコードが今書かれている通りであれば、2番目のスレッドを作成する必要はありません。ただ1行下に参加するだけです。

// handler needs to be attached before starting 
library.ResponseReceived += OnResponseReceived; 

// call the method 
var result = library.DoStuff(); 

// poll and sleep, but 10 times max (5s) 
int watchdog = 10; 
while (_delayedResponse == null && watchdog-- > 0) 
    Thread.Sleep(500); 

// detach handler - always clean up after yourself 
library.ResponseReceived -= OnResponseReceived; 

Console.WriteLine(_delayedResponse != null); 

この作品、そしてあなたがWinFormsのアプリケーションをプログラミングしている場合は、バックグラウンドスレッドで全体ことをやって、それが終了だときUIに通知検討すべきです。もちろん、もしあなたがそれについて助けを必要とするならば、より多くの詳細を提供する必要があります。

+0

バックグラウンドスレッドを生成しないようです。私はこれまでと同じことをしています。待っているとすぐにイベントが発生します。 – xsl

関連する問題