- - PR -
別スレッドからのコールバックの結果を安全に呼出元に渡すには?
1
投稿者 | 投稿内容 | ||||
---|---|---|---|---|---|
|
投稿日時: 2005-09-02 04:55
いつもお世話になっています。
今までは1つの関数で行っていた処理を、他と共通のサーバを使って実現するように変更することになりました。今までは単純にシングルスレッドで結果を関数の戻り値として返していたのですが、新しいサーバでは、リクエストとは別スレッドを作って、結果はイベントで知らせてきます。今あるAPIの仕様を変更するわけにもいかないので、イベントで戻ってきた結果を元の関数から渡す必要があります。以下のような方法でとりあえず実現は出来そうなのですが、自分でやりながらかなり気持ちが悪いです。 なにかもっと良い方法は無いでしょうか。よろしくお願いします。 // 結果受渡しのためだけに作成 private ResultType m_result; ResultType ProcessCalc() { m_result = null; ResultType result = new ResultType(); // 処理後のコールバックが CompletedCallback に来る CalcClass.CompleteEvent = new ComepleteEventHandler(CompletedCallback); // このメソッド内で、別スレッドを作って処理を行う(この中身は変更不可)。終了後コールバックが起こる CalcClass.Process(); // 処理終了まで待機 Monitor.Enter(this); Monitor.Wait(this, 5000); result = m_result; Monitor.Exit(this); return result; } void CompletedCallback(object sender, ResultEventArgs e) { Monitor.Enter(this); m_result = e.Result; //結果を保存 Monitor.Pulse(this); Monitor.Exit(this); } | ||||
|
投稿日時: 2005-09-04 09:57
ProcessCalc内のMonitor.Enter(this)と、CompletedCallback内のMonitor.Enter(this)がデッドロックを起こしませんか?書き換える変数がm_resultだけなら、クリティカルセクションを設ける必要は無いはずです。
また、この実装では運が悪いとPulseを受け取りそびれる事になりますね。Monitor.Waitを呼び出す前に、CompletedCallbackが呼ばれるとデッドロックするでしょう。 これを踏まえて修正すると、↓な感じ
この実装ではスレッドセーフではありません。スレッドセーフにしたいなら、ProcessCalc関数内の処理をクリティカルセクションにしてください。 _________________ 甕星 <mikahosi@abox9.so-net.ne.jp> http://blogs.msmvp.jp/mikahosi/ [ メッセージ編集済み 編集者: 甕星 編集日時 2005-09-04 09:58 ] |
1