2013-09-24 66 views
1

在Form1我有這樣的代碼:爲什麼即時關閉我的應用程序時,有時候會出現ObjectDisposeException?

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,因爲即時通訊在Form1中使用backgroundworker和backgroundworker使用這個類,如果即時關閉程序,然後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; 
     } 

添加了調用前行的檢查和還增加try和catch。 那好嗎?或者我應該做的另一種方式爲cpuView和gpuView?

編輯**

這是Form 1中的BackgroundWorker 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; 
         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));      
       } 
      } 
     } 
+0

您的表單在關閉時自動處理。聽起來好像'Core.cpuView()'在窗體關閉後被調用。 – Andy

回答

1

檢查表單調用前設置。

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

此外,在您的for循環的一些內部,您應該添加一個檢查取消,以便後臺工作更快完成。

if (CancellationPending) return; 

即使有了這個,仍然有可能你會得到處置的例外。如果表格在IsDisposed檢查後和Invoke調用之前關閉,那麼您將得到異常。對於這種罕見的情況,添加錯誤處理並忽略它(這是在應用程序關閉時安全忽略的異常)。

+0

Samuel Neff我編輯了我的代碼,如果沒關係,或者如果不告訴我它應該是怎麼樣的,你可以看一下嗎? – user2760148

+0

@ user2760148,你在那裏。您向後臺工作人員添加了取消檢查,但由於cpuview也有一個循環,並且可能會耗費大量時間進行工作,因此應該執行額外的取消檢查。我也沒有看到任何添加的IsDisposed檢查或錯誤處理。 –

+0

我在cpuView和gpuView的調用行之前添加了IsDisposed。關於cancelltion檢查,我必須嘗試去處理它。 – user2760148

相關問題