Cross-Thread Operation Not Valid: Control 'Textbox1' Accessed from a Thread Other Than the Thread It Was Created On

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

The data received in your serialPort1_DataReceived method is coming from another thread context than the UI thread, and that's the reason you see this error.

To remedy this, you will have to use a dispatcher as descibed in the MSDN article:

How to: Make Thread-Safe Calls to Windows Forms Controls

So instead of setting the text property directly in the serialport1_DataReceived method, use this pattern:

delegate void SetTextCallback(string text);

private void SetText(string text)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (this.textBox1.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { text });
}
else
{
this.textBox1.Text = text;
}
}

So in your case:

private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
txt += serialPort1.ReadExisting().ToString();
SetText(txt.ToString());
}

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

As per Prerak K's update comment (since deleted):

I guess I have not presented the question properly.

Situation is this: I want to load data into a global variable based on the value of a control. I don't want to change the value of a control from the child thread. I'm not going to do it ever from a child thread.

So only accessing the value so that corresponding data can be fetched from the database.

The solution you want then should look like:

UserContrl1_LOadDataMethod()
{
string name = "";
if(textbox1.InvokeRequired)
{
textbox1.Invoke(new MethodInvoker(delegate { name = textbox1.text; }));
}
if(name == "MyName")
{
// do whatever
}
}

Do your serious processing in the separate thread before you attempt to switch back to the control's thread. For example:

UserContrl1_LOadDataMethod()
{
if(textbox1.text=="MyName") //<<======Now it wont give exception**
{
//Load data correspondin to "MyName"
//Populate a globale variable List<string> which will be
//bound to grid at some later stage
if(InvokeRequired)
{
// after we've done all the processing,
this.Invoke(new MethodInvoker(delegate {
// load the control with the appropriate data
}));
return;
}
}
}

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

You can't access UI elements from just any thread - it must be on the UI thread. With a handler like that, you can't assume you are on the UI thread and actually you should assume you may not be. The way you ensure a UI control is accessed properly, always check if InvokeRequired before accessing it.

Dim text As String
If control.InvokeRequired Then
control.Invoke(Sub() text = control.Text)
Else
text = control.Text
End If

In your case, the issue is in HandleUpdateAsync. The line of code

Await botClient.SendTextMessageAsync("chatid", RichTextBox1.Text)

could be changed to

Dim text As String
If RichTextBox1.InvokeRequired Then
RichTextBox1.Invoke(Sub() text = RichTextBox1.Text)
Else
text = RichTextBox1.Text
End If
Await botClient.SendTextMessageAsync("chatid", text)

The accepted way to do this is not inline in the code like that. Your google search has found it. Generally, it's like this

Private Function GetRichTextBox1Text() As String
If RichTextBox1.InvokeRequired Then
Return RichTextBox1.Invoke(AddressOf GetRichTextBox1Text)
Else
Return RichTextBox1.Text
End If
End Function
Await botClient.SendTextMessageAsync("chatid", GetRichTextBox1Text())

Nobody wants to do this all the time. You can write extension methods (for action and simple function) in a Module like this, and of course you can extrapolate on these for any number of arguments

<Extension(), DebuggerHidden()>
Public Sub InvokeIfRequired(control As Control, action As MethodInvoker)
If control.InvokeRequired Then control.Invoke(action) Else action()
End Sub
' No parameters
<Extension(), DebuggerHidden()>
Public Function InvokeIfRequired(Of TR)(control As Control, func As Func(Of TR)) As TR
If control.InvokeRequired Then
Return control.Invoke(func)
Else
Return func.Invoke()
End If
End Function
' One parameter
<Extension(), DebuggerHidden()>
Public Function InvokeIfRequired(Of T1, TR)(control As Control, func As Func(Of T1, TR), arg1 As T1) As TR
If control.InvokeRequired Then
Return CType(control.Invoke(func, arg1), TR)
Else
Return func.Invoke(arg1)
End If
End Function
' n parameters can be extrapolated...

In your case, use the function

Await botClient.SendTextMessageAsync("chatid", RichTextBox1.InvokeIfRequired(Function() RichTextBox1.Text))

Textbox value using threading ?Cross-thread operation not valid

You cannot access UI controls other than UI thread. Try following code.

public  void CallToChildThread()
{
string test1 = "this is 1st";
string test2 = "this is 2nd";
string test3 = "this is 3rd";

this.Invoke((MethodInvoker)delegate
{
textBox1.Text = test1; //Cross-thread operation not valid
});

int sleepfor = 5000;
Thread.Sleep(sleepfor);

this.Invoke((MethodInvoker)delegate
{
textBox1.Text = "Child Thread 1 Paused for {0} seconds '"+sleepfor/1000+"' ";
textBox1.Text = test3;
textBox1.Text = test4;
});

Thread.Sleep(sleepfor);

this.Invoke((MethodInvoker)delegate
{
textBox1.Text = "Child Thread 2 Paused for {0} seconds '" + sleepfor / 1000 + "' ";
textBox1.Text = test5;
});
}

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

Try this:

this.BeginInvoke((Action)(() => toolStripStatusLabel1.Text = "This text was set safely."));

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

As per Prerak K's update comment (since deleted):

I guess I have not presented the question properly.

Situation is this: I want to load data into a global variable based on the value of a control. I don't want to change the value of a control from the child thread. I'm not going to do it ever from a child thread.

So only accessing the value so that corresponding data can be fetched from the database.

The solution you want then should look like:

UserContrl1_LOadDataMethod()
{
string name = "";
if(textbox1.InvokeRequired)
{
textbox1.Invoke(new MethodInvoker(delegate { name = textbox1.text; }));
}
if(name == "MyName")
{
// do whatever
}
}

Do your serious processing in the separate thread before you attempt to switch back to the control's thread. For example:

UserContrl1_LOadDataMethod()
{
if(textbox1.text=="MyName") //<<======Now it wont give exception**
{
//Load data correspondin to "MyName"
//Populate a globale variable List<string> which will be
//bound to grid at some later stage
if(InvokeRequired)
{
// after we've done all the processing,
this.Invoke(new MethodInvoker(delegate {
// load the control with the appropriate data
}));
return;
}
}
}

VB.NET [Cross-thread operation not valid: Control 'txtIncomingText' accessed from a thread........]

Well, you should invoke the calls on the control's thread. This is a quick and dirty solution

Dim message = Encoding.ASCII.GetString(dataBuf)
txtIncomingText.Invoke(Sub() txtIncomingText.Text = message)
rbChat.Invoke(Sub() rbChat.Text = Environment.NewLine & "Server: " & message)

But you should check if invocation is required first. See https://msdn.microsoft.com/en-us/library/ms171728(v=vs.110).aspx

Also, "\n" is not how you make a new line in vb.net (did you copy this code from c#?).

And + is not how you concatenate strings in vb.net (see above parenthesis).



Related Topics



Leave a reply



Submit