控制从C#

时间:2016-11-14 14:51:26

标签: c# multithreading arduino serial-port

所以我有一个按钮,最近能通过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

1 个答案:

答案 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; });