完了したら UI を更新するバックグラウンド スレッドがあります。Disposed された GUI を呼び出さないように、できるだけ安全にしようとしました。
void DoInBackground()
{
try
{
string result = ServerSideProcess();
* if (!IsDisposed && !Disposing)
* BeginInvoke(new StringDelegate(UpdateText), result);
}
catch (Exception ex)
{
* if (!IsDisposed && !Disposing)
* BeginInvoke(new VoidDelegate(UpdateFailed));
}
}
void UpdateText(string txt)
{
if (!IsDisposed && !Disposing)
textbox1.Text = txt;
}
void UpdateFailed()
{
if (!IsDisposed && !Disposing)
textbox1.Text = "failed to get data from server";
}
override Dispose(bool disposing)
{
if (disposing)
{
if (components != null)
components.Dispose();
}
base.Dispose(disposing);
}
GUIメソッド内では十分に安全だと思います.UpdateText(string)またはUpdateFailed()内にいる間はDispose()は呼び出されません。どちらも同じスレッドで実行されるためです。 IsDisposing の場合は、後で実行するだけで十分です。しかし、(*) 内の部分が Dispose() を途中で取得しないことを確認するにはどうすればよいでしょうか。その結果、破棄するクラスで BeginInvoke が呼び出され、最終的にアプリケーションがクラッシュします。
(*) 部分の間に Thread.Sleep(2000) を追加し、Thread.Sleep の前後にブレークポイントを配置し、コントロールの外に移動して、BeginInvoke に到達する前に Dispose()d を取得することでテストしました。結果 - アプリケーションがクラッシュしました。ランタイムがこの不幸なコンテキスト切り替えシナリオを提供しないことをどのように知ることができますか?