我有这个功能:
public void NudgeMe()
{
int xCoord = this.Left;
int yCoord = this.Top;
int rnd = 0;
Random RandomClass = new Random();
for (int i = 0; i <= 500; i++)
{
rnd = RandomClass.Next(xCoord + 1, xCoord + 15);
this.Left = rnd;
rnd = RandomClass.Next(yCoord + 1, yCoord + 15);
this.Top = rnd;
}
this.Left = xCoord;
this.Top = yCoord;
}
我在这里调用这个函数:
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);
}
}
}
我得到的异常是:invalidOperationException 跨线程操作无效:从
上创建的线程以外的线程访问控制'Form1'例外是在NudgeMe()中的行:
this.Left = rnd;
该线涂成绿色。
System.InvalidOperationException was unhandled by user code
Message=Cross-thread operation not valid: Control 'Form1' 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.SetBoundsCore(Int32 x, Int32 y, Int32 width, Int32 height, BoundsSpecified specified)
at System.Windows.Forms.Form.SetBoundsCore(Int32 x, Int32 y, Int32 width, Int32 height, BoundsSpecified specified)
at System.Windows.Forms.Control.SetBounds(Int32 x, Int32 y, Int32 width, Int32 height, BoundsSpecified specified)
at System.Windows.Forms.Control.set_Left(Int32 value)
at HardwareMonitoring.Form1.NudgeMe() in D:\C-Sharp\HardwareMonitoring\HardwareMonitoring\Hardwaremonitoring\Form1.cs:line 782
at HardwareMonitoring.Form1.backgroundWorker1_DoWork(Object sender, DoWorkEventArgs e) in D:\C-Sharp\HardwareMonitoring\HardwareMonitoring\Hardwaremonitoring\Form1.cs:line 727
at System.ComponentModel.BackgroundWorker.OnDoWork(DoWorkEventArgs e)
at System.ComponentModel.BackgroundWorker.WorkerThreadStart(Object argument)
InnerException:
答案 0 :(得分:3)
您只能与创建它的线程中的控件(或表单)进行交互。您的例外被抛出,因为您正在与第二个帖子中的表单进行交互。
要修复你拥有的内容,请查看表单上的Invoke或BeginInvoke方法 - 它们允许您传递将在表单的线程上执行的委托(这称为“编组”)
更好: 而不是输入While和sleep,使用计时器。如果您在Windows窗体命名空间中使用计时器,它将为您处理编组问题,因此您甚至不需要使用调用
答案 1 :(得分:1)
您需要将修改同步到表单的SynchronizationContext
。
修改与UI线程位于不同的线程中 - 因此是跨线程异常。
// get a reference to the form's sync-context
SynchronizationContext _sync = SynchronizationContext.Current;
_sync.Send((state) => {
// code to modify UI objects
}
答案 2 :(得分:1)
this.Invoke((MethodInvoker) delegate {
this.Left = rnd;
});
答案 3 :(得分:1)
发生错误是因为必须在创建它们的同一线程上操作UI组件。您的后台工作人员正在以不同的方式运作。
您可以使用InvokeRequired
和回调来让UI线程完成工作。
public void NudgeMe() {
if( this.InvokeRequired ) {
Action callBack = NudgeMe;
this.Invoke( callBack );
} else {
int xCoord = this.Left;
int yCoord = this.Top;
int rnd = 0;
Random RandomClass = new Random();
for( int i = 0; i <= 500; i++ ) {
rnd = RandomClass.Next( xCoord + 1, xCoord + 15 );
this.Left = rnd;
rnd = RandomClass.Next( yCoord + 1, yCoord + 15 );
this.Top = rnd;
}
this.Left = xCoord;
this.Top = yCoord;
}
}
答案 4 :(得分:0)
从后台线程更改UI线程是一个很大的禁忌。您可以从后台工作者中删除直接访问UI的代码,也可以查看此问题......