MDI ベースのグラフ作成アプリケーションがあります。各子フォームは、グラフを含むフォームです。各グラフには、独自のデータ キューと専用のワーカー スレッドがあります。
ワーカー スレッドの DoWork メソッドには、グラフにデータをプロットする bool "IsChartActive" によって制御される while ループがあります。データをプロットするには、chartForm 自体で Invoke を呼び出し、グラフを更新するメソッドにデリゲートを渡します。
ユーザーがグラフ フォームを閉じると、実際に閉じるのではなく、グラフの更新を停止し、ユーザーが再度表示するまでグラフを非表示にしたいと考えています。
これを行うには、FormClosing イベントを処理し、Cancel = true に設定し、"IsChartActive = false" に設定して、ChartForm.Hide() を呼び出します。
しかし、この後、DoWork メソッドで「破棄されたオブジェクトにアクセスできません」という例外が発生します (これは、「IsChartActive = false」を設定したときにバックグラウンド スレッドが既に呼び出しステートメントにあるために発生すると想定しているため、変更が表示されます次の反復で)、チャートで invoke を呼び出すとき。
グラフが実際には破棄されておらず、非表示になっているだけなのに、なぜこの例外が発生するのですか?
public void StopChartUpdates()
{
IsActive = false;
updateChartThread.CancelAsync();
}
private void updateChartThread_DoWork(object sender, DoWorkEventArgs e)
{
while (IsActive && !updateChartThread.CancellationPending)
{
try
{
ChartView.Invoke(new Action(InvokeOnUiThread));
}
catch (ObjectDisposedException ex)
{
//getting this error when calling invoke on ChartView
Trace.WriteLine("Exception: " + ex.Message);
}
Thread.Sleep(UpdateFrequency);
}
}
private void InvokeOnUiThread()
{
try
{
//update the chart
}
catch (Exception ex)
{
Trace.WriteLine("Exception: " + ex.Message);
}
}
private void ChartView_FormClosing(object sender, System.Windows.Forms.FormClosingEventArgs e)
{
StopChartUpdates();
if (e.CloseReason == CloseReason.UserClosing)
{
ChartView.Hide();
e.Cancel = true;
}
}