0

So I have a button that lately will be capable of open a door through SerialPort. To do that I will send something to it and wait for a response from it which is already configured and developed.

But I am getting some trouble to set a Thread.Sleep().

This is what I got inside of the button:

private void cmdOpenDoor_Click(object sender, EventArgs e)
{
    Thread.Sleep(5000);
    Task.Factory.StartNew(this.Demo);
}

And the Demo method is:

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

When I will open the door it shows the "Door opened" message and when it tries to execute the pbGreen.Show() the applications stops and an error comes:

Cross-thread operation not valid: Control accessed from a thread other than the thread it was created on

Do you have any idea how can I solve it? I cannot Invoke a PictureBox

Forrobodo
  • 49
  • 2
  • 2
  • 9
  • 4
    Search for exact error message, e.g. [here](http://stackoverflow.com/q/142003/1997232) is duplicate for winforms and [here](http://stackoverflow.com/q/11923865/1997232) is for wpf. – Sinatr Nov 14 '16 at 14:52
  • This is not a `TextBox` it's a `PictureBox` @Sinatr – Forrobodo Nov 14 '16 at 14:58
  • The problem is irrelevant to control type and yes, you can *invoke a `PictureBox`*. I would start with reading corresponding linked questions answers, if it's still not clear what you need to do, then: 1) add corresponding tag to the question (winforms? wpf? ...) 2) explain why you *"cannot Invoke"*. The message you receive should gone as soon as you dispatch/invoke GUI related stuff into GUI thread. – Sinatr Nov 14 '16 at 15:01

1 Answers1

0

As the control you're trying to access (in this instance pbGreen and most likely pbRed as well) were created on the Main Thread, and you're trying to update them on a differnet thread, you get this error. To fix the issue, you need to make your calls thread-safe by invoking.

private void Demo()
{
    if (InvokeRequired) {
        Invoke(new MethodInvoker(() => { Demo(); }));
        return;
    }

    //Do stuff
}

However making your own method could be even better:

public static void InvokeIfRequired(this ISynchronizeInvoke formControl, MethodInvoker action)
{
    if (formControl.InvokeRequired) {
        formControl.Invoke(action, new object[0]);
    } else {
        action();
    }
}

Then:

pbGreen.InvokeIfRequired(() => { pbGreen.Image = myImage; });
Mark Phillips
  • 273
  • 1
  • 8