我有这个功能:
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:
我该如何解决/修复它?
答案 0 :(得分: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!";
}
答案 1 :(得分:1)
您正尝试从后台线程访问UI - 因此“跨线程操作无效:”消息。
您需要从后台工作程序向UI线程发送事件,并使用Invoke
更新UI。在这里,我将它作为扩展方法实现,因此可以从任何控件中调用它:
public static void InvokeIfRequired(this Control control, Action action)
{
if (control.InvokeRequired)
{
control.Invoke(action);
}
else
{
action();
}
}
其中control
是您要更新的UI元素,action()
是您要调用的方法。然后你可以这样称呼它:
this.label17.InvokeIfRequired(() => this.label17.UpdateLabel(sensor.Value.ToString() + "c"));
private static void UpdateLabel(this Label label, string newValue)
{
label.Text = newValue;
}