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

1

所以这里的部分问题是您没有利用 BGW 为您提供的功能。如果您Invoke从内部调用,DoWork则意味着您并没有真正使用 BGW 来完成它的工作。在您的情况下,您应该只调用ReportProgressBGW,然后有一个ProgressChanged事件处理程序根据进度更新 UI。您可以传入一个表示要更新 UI 的数据的参数,因此您可以在 内部构造列表DoWork,通过 传递它ReportProgress,然后DataSourceProgressChanged事件处理程序中设置 。

现在,一旦工人被取消,BGW 负责不报告进度。

于 2013-03-07T20:48:46.027 回答
0

当 Form 关闭时,它的子控件和表单本身都会被释放。但是,WinForms 继续处理 UI 线程上的未决调用。这就是为什么它会引发“无法访问已处置的对象”。

Application.DoEvents()通常被描述为邪恶,但它的工作是处理 UI 线程上的所有待处理消息。

在 Close 事件中完成后台线程是不够的。

这就是为什么我建议您Application.DoEvents()在任何 Dispose 之前添加一个,以便刷新待处理的调用,然后表单将优雅地关闭。

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 回答