为什么我在关闭应用程序时有时会收到 ObjectDisposeException

本文关键字:ObjectDisposeException 应用程序 为什么 | 更新日期: 2023-09-27 18:32:42

在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
            {
                this.backgroundWorker1.CancelAsync();                
            }

        }

然后我有一个新的课程,我做了:

class Core
    {
        public static Form1 form1;
        public Core(Form1 f)
        {
            form1 = f;
        }
        public static float? cpuView(bool pause , CpuTemperature cpuTemp , Form1 f1 , List<string> myData , float? myCpuTemp , Button b1)
        {
            if (pause == true)
            {
            }
            else
            {
                Computer myComputer = new Computer();
                myComputer = new Computer(cpuTemp)
                {
                    CPUEnabled =
                        true
                };
                myComputer.Open();
                Trace.WriteLine("");
                foreach (var hardwareItem in myComputer.Hardware)
                {
                    if (hardwareItem.HardwareType == HardwareType.CPU)
                    {
                        hardwareItem.Update();
                        foreach (IHardware subHardware in hardwareItem.SubHardware)
                            subHardware.Update();
                        foreach (var sensor in hardwareItem.Sensors)
                        {
                            cpuTemp.SetValue("sensor", sensor.Value.ToString());
                            if (sensor.SensorType == SensorType.Temperature)
                            {
                                sensor.Hardware.Update();
                                cpuTemp.GetValue("sensor", sensor.Value.ToString());                                
                                f1.Invoke(new Action(() => myData.Add("Cpu Temeprature --- " + sensor.Value.ToString())));
                                myCpuTemp = sensor.Value;
                                if (sensor.Value > 60)
                                {

                                    Logger.Write("The Current CPU Temperature Is ===> " + sensor.Value);
                                    b1.Enabled = true;
                                }
                                break;
                            }
                        }
                    }
                }
            }
            return myCpuTemp;
        }

例外情况如下:

f1.Invoke(new Action(() => myData.Add("Cpu Temeprature --- " + sensor.Value.ToString())));

我认为造成问题的处置对象是 Form1 它自己。

System.ObjectDisposedException was unhandled by user code
  HResult=-2146232798
  Message=Cannot access a disposed object.
Object name: 'Form1'.
  Source=System.Windows.Forms
  ObjectName=Form1
  StackTrace:
       at System.Windows.Forms.Control.MarshaledInvoke(Control caller, Delegate method, Object[] args, Boolean synchronous)
       at System.Windows.Forms.Control.Invoke(Delegate method, Object[] args)
       at System.Windows.Forms.Control.Invoke(Delegate method)
       at HardwareMonitoring.Core.cpuView(Boolean pause, CpuTemperature cpuTemp, Form1 f1, List`1 myData, Nullable`1 myCpuTemp, Button b1) in d:'C-Sharp'HardwareMonitoring'HardwareMonitoring'Hardwaremonitoring'Core.cs:line 55
       at HardwareMonitoring.Form1.backgroundWorker1_DoWork(Object sender, DoWorkEventArgs e) in d:'C-Sharp'HardwareMonitoring'HardwareMonitoring'Hardwaremonitoring'Form1.cs:line 427
       at System.ComponentModel.BackgroundWorker.OnDoWork(DoWorkEventArgs e)
       at System.ComponentModel.BackgroundWorker.WorkerThreadStart(Object argument)
  InnerException: 

那么什么是处置的?因为我没有在我的代码中做一些事情来处置()它。

也许问题是 Form1,

因为 im 在 Form1 中使用了后台工作者,而后台工作者正在使用这个类,如果 im 关闭程序,那么 form1 被释放,但也许变量 f1 仍在尝试做某事?

我该如何解决?

编辑**

更改了 cpuView 函数:

public static float? cpuView(bool pause , CpuTemperature cpuTemp , Form1 f1 , List<string> myData , float? myCpuTemp , Button b1)
        {
            try
            {
                if (pause == true)
                {
                }
                else
                {
                    Computer myComputer = new Computer();
                    myComputer = new Computer(cpuTemp)
                    {
                        CPUEnabled =
                            true
                    };
                    myComputer.Open();
                    Trace.WriteLine("");
                    foreach (var hardwareItem in myComputer.Hardware)
                    {
                        if (hardwareItem.HardwareType == HardwareType.CPU)
                        {
                            hardwareItem.Update();
                            foreach (IHardware subHardware in hardwareItem.SubHardware)
                                subHardware.Update();
                            foreach (var sensor in hardwareItem.Sensors)
                            {
                                cpuTemp.SetValue("sensor", sensor.Value.ToString());
                                if (sensor.SensorType == SensorType.Temperature)
                                {
                                    sensor.Hardware.Update();
                                    cpuTemp.GetValue("sensor", sensor.Value.ToString());
                                    if (!f1.IsDisposed)
                                    {
                                        f1.Invoke(new Action(() => myData.Add("Cpu Temeprature --- " + sensor.Value.ToString())));
                                    }
                                    myCpuTemp = sensor.Value;
                                    if (sensor.Value > 60)
                                    {

                                        Logger.Write("The Current CPU Temperature Is ===> " + sensor.Value);
                                        b1.Enabled = true;
                                    }
                                    break;
                                }
                            }
                        }
                    }
                }
            }
            catch(Exception err)
            {
                return null;
            }
            return myCpuTemp;
        }

在调用行之前添加了检查,还添加了尝试和捕获。可以吗?或者我应该为cpuView和gpuView做另一种方式?

编辑**

这是 Form1 中的后台工作线程执行工作事件:

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;
                        NudgeMe();
                    }
                    else
                    {
                        soundPlay = false;
                        stop_alarm = true;
                    }
                    tempCpuValue = Core.cpuView(pauseContinueDoWork,cpu,this,data,tempCpuValue,button1);
                    tempGpuValue = Core.gpuView(pauseContinueDoWork,data,tempGpuValue,button1);
                    this.Invoke(new Action(() => data = new List<string>()));
                    tempCpuValue = Core.cpuView(pauseContinueDoWork, cpu, this, data, tempCpuValue, button1);
                    tempGpuValue = Core.gpuView(pauseContinueDoWork, data, tempGpuValue, button1);
                    this.Invoke(new Action(() => listBox1.DataSource = null));
                    this.Invoke(new Action(() => listBox1.DataSource = data));                    
                }
            }
        }

为什么我在关闭应用程序时有时会收到 ObjectDisposeException

在调用表单之前检查表单是否已释放。

if (!f1.IsDisposed)
{
    f1.Invoke(new Action(() => myData.Add("Cpu Temeprature --- " + sensor.Value.ToString())));
}

此外,在某些 for 循环中,您应该添加取消检查,以便后台工作线程更快地完成。

if (CancellationPending) return;

即使这样,您仍然有可能得到已处理的异常。 如果表单在IsDisposed检查之后和Invoke调用之前关闭,则会出现异常。 对于这种罕见的情况,请添加错误处理并忽略它(这是一个在应用程序关闭时可以安全忽略的异常)。

相关文章:
  • 没有找到相关文章