ほとんどの場合、このコードは機能するので、競合状態を考えています。結果クラスは不変ですが、そのクラスに問題があるとは思いません。
public Result GetResult()
{
using (var waitHandle = new ManualResetEvent(false))
{
Result result = null;
var completedHandler = new WorkCompletedEventHandler((o, e) =>
{
result = e.Result;
// somehow waitHandle is closed, thus exception occurs here
waitHandle.Set();
});
try
{
this.worker.Completed += completedHandler;
// starts working on separate thread
// when done, this.worker invokes its Completed event
this.worker.RunWork();
waitHandle.WaitOne();
return new WorkResult(result);
}
finally
{
this.worker.Completed -= completedHandler;
}
}
}
編集: 申し訳ありませんが、GetResult() メソッドを呼び出す直前に this.worker.RunWork() を呼び出していませんでした。Completed イベントが 2 回発生したにもかかわらず、waitHandle.Set()の前に waitHandle が閉じられた理由はわかりませんが、これにより (時々) 同じジョブが 2 回実行されたようです。これは IO 作業をまったく損なうものではありません (結果は正しかったです。コードを変更して手動でwaitHandleを閉じた後)。
したがって、質問が完全ではなかったとしても、 Iridiumの回答は(正しい回答ではないにしても)最も近い回答になるはずです。