4

基になる非同期オブジェクトの状態を表示するコントロールがあります。オブジェクトはイベントを発生させます。イベントはフォームに到着し、基本的にキューに入れられ、最終的にBeginInvokeを使用して呼び出されます。

コントロールを廃棄すると問題が発生します。物事は非同期で発生しているため、廃棄中にイベントコールバックがキューに入れられる可能性が常にあるため、InvalidOperationExceptionが発生することがあります(ウィンドウハンドルが作成されるまで、コントロールでInvokeまたはBeginInvokeを呼び出すことはできません)。

これは私が望む振る舞いではありません。コントロールが破棄された場合でもコールバックを実行したい(コールバックで例外が発生した場合でも、それは私にとってはるかに便利な例外です!)。各コールバックで破棄された状態の動作を処理したい(通常は破棄された場合はスキップしますが、場合によっては[たとえば、1つのコントロールがイベントをログに記録し(オプションでファイルに)、ログデータを失いたくない!])。

私が望むように機能する方法はありますか?もろくないものを自分で書くことはできますか?

4

1 に答える 1

6

SynchronizationContext.Current代わりに試してください。これには、とに大まかにマップするPostSendメンバーがあります。これらの操作は、UIスレッドが特定のコントロールに対して有効である限り、機能し続けます。BeginInvokeInvokeControl

このタイプSynchronizationContextはWinFormsに固有のものではなく、それを利用するソリューションはWPFなどの他のフレームワークに移植可能です。

例えば。

BeginInvokeコード

void OnButtonClicked() {
  DoBackgroundOperation(this); 
}

void DoBackgroundOperation(ISynchronizedInvoke invoke) {
  ThreadPool.QueueUserWorkItem(delegate { 
    ...
    delegate.BeginInovke(new MethodInvoker(this.BackgroundOperationComplete), null);
  });
}

彼らのSynchronizationContextコード

void OnButtonClicked() {
  DoBackgroundOperation(SynchronizationContext.Current);
}

void DoBackgroundOperation(SynchronizationContext context) {
  ThreadPool.QueueUserWorkItem(delegate {
    ...
    context.Post(delegate { this.BackgroundOperationComplete() }, null);
  });
}
于 2010-12-22T21:16:47.333 に答える