所以我有一个按钮,最近能通过SerialPort
打开一扇门。要做到这一点,我会向它发送一些内容并等待已经配置和开发的响应。
但是我设置Thread.Sleep()
时遇到了一些麻烦。
这就是我在按钮里面的内容:
private void cmdOpenDoor_Click(object sender, EventArgs e)
{
Thread.Sleep(5000);
Task.Factory.StartNew(this.Demo);
}
Demo
方法是:
private void Demo()
{
string questionMark= "?";
string incoming = comport.ReadExisting();
string carriageReturn = "\r";
comport.Write(questionMark+ "(" + carriageReturn);
Cursor.Current = Cursors.WaitCursor;
if (txtTest.Text == "@q")
{
MessageBox.Show("Door opened!", MessageBoxButtons.OK, MessageBoxIcon.Information);
pbGreen.Show();
pbRed.Hide();
}
else
{
MessageBox.Show("The door is already opened!", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
当我打开门时,它会显示"门打开"消息,当它尝试执行pbGreen.Show()
时,应用程序停止并出现错误:
跨线程操作无效:从
上创建的线程以外的线程访问控件
你知道我该如何解决它?我无法调用PictureBox
答案 0 :(得分:0)
由于您尝试访问的控件(在本例中为pbGreen,并且很可能也是pbRed)是在主线程上创建的,并且您尝试在不同的线程上更新它们,您会收到此错误。 要解决此问题,您需要通过调用来使您的调用成为线程安全的。
private void Demo()
{
if (InvokeRequired) {
Invoke(new MethodInvoker(() => { Demo(); }));
return;
}
//Do stuff
}
然而,制作自己的方法可能会更好:
public static void InvokeIfRequired(this ISynchronizeInvoke formControl, MethodInvoker action)
{
if (formControl.InvokeRequired) {
formControl.Invoke(action, new object[0]);
} else {
action();
}
}
然后:
pbGreen.InvokeIfRequired(() => { pbGreen.Image = myImage; });