1

DoWorkバックグラウンドイベントに次のコードがあります。

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    BackgroundWorker worker = sender as BackgroundWorker;
    while (true)
    {

        if ((worker.CancellationPending == true))
        {
            e.Cancel = true;
            break;
        }
        else
        {
            if (tempCpuValue >= (float?)nud1.Value || tempGpuValue >= (float?)nud1.Value)
            {
                soundPlay = true;
                blinking_label();
                NudgeMe();
            }
            else
            {
                soundPlay = false;
                stop_alarm = true;

            }
            cpuView();
            gpuView();
        }
    }
}

cpuView()メソッドには、次のコードがあります。

if (InvokeRequired)
{
    this.Invoke(new Action(() => data = new List<string>()));
    this.Invoke(new Action(() => data.Add("Gpu Temeprature --- " + sensor.Value.ToString())));
    this.Invoke(new Action(() => listBox1.DataSource = null));
    this.Invoke(new Action(() => listBox1.DataSource = data));
    this.Invoke(new Action(() => listBox1.Invalidate()));
}

今回は例外/エラーが次の行にありました。

this.Invoke(new Action(() => data = new List<string>()));

そして、これは私の Form1 クロージング イベントです:

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    if (MessageBox.Show("Are you Sure you want to Exit. Click Yes to Confirm and No to continue", "WinForm", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No)
    {
        e.Cancel = true;
    }
    else
    {
        if (backgroundWorker1.WorkerSupportsCancellation == true)
        {
            backgroundWorker1.CancelAsync();
        }
    }
}

右上隅の赤い x をクリックしてアプリケーションを終了し、[はい] を選択して終了すると、エラー/例外が発生しました。

私は何をすべきか ?

4

2 に答える 2

0

フォームが閉じられると、その子コントロールとフォーム自体が破棄されます。ただし、WinForms は UI スレッドで保留中の呼び出しを処理し続けます。そのため、「破棄されたオブジェクトにアクセスできません」というエラーが発生します。

Application.DoEvents()多くの場合、悪として説明されますが、その仕事は、UI スレッドで保留中のすべてのメッセージを処理することです。

Close イベントでバックグラウンド スレッドを終了させるだけでは十分ではありません。

そのため、Dispose の前に を追加することをお勧めしますApplication.DoEvents()。これにより、保留中の Invoke がフラッシュされ、フォームが正常に閉じられます。

if (MessageBox.Show("Are you Sure you want to Exit. Click Yes to Confirm and No to continue", "WinForm", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No)
{
    e.Cancel = true;
}
else
{
    if (backgroundWorker1.WorkerSupportsCancellation == true)
    {
        backgroundWorker1.CancelAsync();
    }

    Application.DoEvents();
}

Application.DoEvents() が難解すぎる場合は、InvokeRequired パターンをカプセル化する拡張メソッドを使用して ObjectDisposedException を飲み込むことができます。

public static void InvokeIfRequired(this Control control, Action action)
{
    try
    {
        if (control.IsDisposed)
            return;

        if (control.InvokeRequired)
            control.Invoke(action);
        else
            action();
    }
    catch (ObjectDisposedException)
    {
        // There is nothing much we can do when an Invoke is pending on a disposed control 
        // the other exceptions will bubble up normally
    }
}
于 2013-06-14T17:46:27.417 に答える