2013-03-02 81 views
0

我有这样的功能:如何在使用BakcgroundWorker时避免invalidOperationException?

private void cpuView() 
     { 
      if (pauseContinueDoWork == true) 
      { 
      } 
      else 
      { 
       Computer myComputer = new Computer(); 
       myComputer = new Computer(settings) { 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) 
         { 
          settings.SetValue("sensor", sensor.Value.ToString()); 
          if (sensor.SensorType == SensorType.Temperature) 
          { 
           sensor.Hardware.Update(); 
           settings.GetValue("sensor", sensor.Value.ToString()); 
           label17.Text = sensor.Value.ToString() + "c";//String.Format("{0} Temperature = {1}c", sensor.Name, sensor.Value.HasValue ? sensor.Value.Value.ToString() : "no value"); 
           tempCpuValue = sensor.Value; 
           if (sensor.Value > 60) 
           { 
            Logger.Write("The Current CPU Temperature Is ===> " + sensor.Value); 
            button1.Enabled = true; 
           } 
           int t = label17.Text.Length; 
           if (t >= 4) 
           { 
            label17.Location = new Point(50, 50); // not working to check everything about the locations \\ 

           } 
           else 
           { 
            label17.Location = new Point(50, 50); 
           } 

           break; 
          } 
         } 
        } 
       } 
      } 
     } 

我打电话在后台工作这个功能(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(); 
        Thread.Sleep(1000); 
       } 
      } 
     } 

在这种情况下,唯一的例外是在cpuview功能上这条线:

label17.Text = sensor.Value.ToString() + "c"; 

错误消息是:跨线程操作无效:控制'label17'从其创建的线程以外的线程访问。

异常消息:

System.InvalidOperationException was unhandled by user code 
    HResult=-2146233079 
    Message=Cross-thread operation not valid: Control 'label17' accessed from a thread other than the thread it was created on. 
    Source=System.Windows.Forms 
    StackTrace: 
     at System.Windows.Forms.Control.get_Handle() 
     at System.Windows.Forms.Control.set_WindowText(String value) 
     at System.Windows.Forms.Control.set_Text(String value) 
     at System.Windows.Forms.Label.set_Text(String value) 
     at HardwareMonitoring.Form1.cpuView() in d:\C-Sharp\HardwareMonitoring\HardwareMonitoring\Hardwaremonitoring\Form1.cs:line 378 
     at HardwareMonitoring.Form1.backgroundWorker1_DoWork(Object sender, DoWorkEventArgs e) in d:\C-Sharp\HardwareMonitoring\HardwareMonitoring\Hardwaremonitoring\Form1.cs:line 655 
     at System.ComponentModel.BackgroundWorker.OnDoWork(DoWorkEventArgs e) 
     at System.ComponentModel.BackgroundWorker.WorkerThreadStart(Object argument) 
    InnerException: 

如何解决/解决这个问题?

回答

1

您正在尝试从后台线程访问UI - 因此“跨线程操作无效:”消息。

您需要从后台工作人员向UI线程发送事件并使用Invoke来更新UI。在这里,我已经实现了它作为一个扩展方法,因此可以从任意控制被称为:

public static void InvokeIfRequired(this Control control, Action action) 
{ 
    if (control.InvokeRequired) 
    { 
     control.Invoke(action); 
    } 
    else 
    { 
     action(); 
    } 
} 

哪里control是要更新和action()是要调用的方法的UI元素。然后你可以这样调用:

this.label17.InvokeIfRequired(() => this.label17.UpdateLabel(sensor.Value.ToString() + "c")); 

private static void UpdateLabel(this Label label, string newValue) 
{ 
    label.Text = newValue; 
} 
+0

ChrisF即时得到的this.label17.ImvokeIfRequired行错误:错误“System.Windows.Forms.Label”不包含一个定义为“InvokeIfRequired”并且没有找到接受'System.Windows.Forms.Label'类型的第一个参数的扩展方法'InvokeIfRequired'(您是否缺少using指令或程序集引用?)UpdateLabel的同一行上出现同样的错误 – user2065612 2013-03-03 00:46:02

+0

@ user2065612 - InvokeIfRequired是一个扩展方法(我看到的答案并不清楚)。 – ChrisF 2013-03-03 12:10:29

1

你正在从后台线程进入UI线程的调用。您需要使用控制器上的BeginInvoke以使用委托进行更新或使用ReportProgress方法。

例如:

public delegate void InvokeDelegate(); 

private void DoWork() 
{ 
    label17.BeginInvoke(new InvokeDelegate(InvokeMethod)); 
} 

public void InvokeMethod() 
{ 
    label17.Text = "I execute on the UI thread!"; 
} 
相关问题