Reputation: 101
I am trying to update a text box. I thought my threading code would fix the problem, but it does not. Can anyone help with this?
new Thread((ThreadStart)delegate { txtCapacitance.Text = Math.Round(capacitance, 3).ToString(); }).Start();
Gives the following error:
Cross-thread operation not valid: Control 'txtCapacitance' accessed from a thread other than the thread it was created on.
Note that all this is being started by a dataReceived function which is called whenever USB data is received.
Upvotes: 6
Views: 209
Reputation: 186058
UI objects can only be called from the UI thread. This can be accomplished via the Control's Invoke
method:
txtCapacitance.Invoke((Action)(() => { txtCapacitance.Text = Math.Round(capacitance, 3).ToString(); }));
Upvotes: 6
Reputation: 11104
You need to make sure that you update textBox from same thread as you have created it.
For this purpose create yourself class helper like this and use this extensions instead of using normal way (here are couple of extensions i made for myself, but the one interesting you is changeText
):
public static class ControlExtensions {
public static void changeStatus(this Control varControl, bool varState) {
if (varControl.InvokeRequired) {
varControl.BeginInvoke(new MethodInvoker(() => changeStatus(varControl, varState)));
} else {
varControl.Enabled = varState;
}
}
public static void changeText(this Control varControl, string varText) {
if (varControl.InvokeRequired) {
varControl.BeginInvoke(new MethodInvoker(() => changeText(varControl, varText)));
} else {
varControl.Text = varText;
}
}
public static DateTime readDateValue(this DateTimePicker varControl) {
if (varControl.InvokeRequired) {
return (DateTime) varControl.Invoke(new Func<DateTime>(() => readDateValue(varControl)));
} else {
return varControl.Value;
}
}
public static bool ReadStatus(this CheckBox varControl) {
if (varControl.InvokeRequired) {
return (bool) varControl.Invoke(new Func<bool>(() => ReadStatus(varControl)));
}
return varControl.Checked;
}
public static bool ReadStatus(this RadioButton varControl) {
if (varControl.InvokeRequired) {
return (bool) varControl.Invoke(new Func<bool>(() => ReadStatus(varControl)));
}
return varControl.Checked;
}
public static string readText(this Control varControl) {
if (varControl.InvokeRequired) {
return (string) varControl.Invoke(new Func<string>(() => readText(varControl)));
} else {
return varControl.Text;
}
}
public static bool readEnabled(this Control varControl) {
if (varControl.InvokeRequired) {
return (bool) varControl.Invoke(new Func<bool>(() => readEnabled(varControl)));
} else {
return varControl.Enabled;
}
}
}
Then you use it like this: txtCapacitance.changeText("new text");
Upvotes: 0
Reputation: 166506
You should rather have a look at using BackgroundWorker Class
Have a look at
Upvotes: 4
Reputation: 1391
try this one
//delegate
delegate void updateTextboxDelegate(string value);
private void updateDisplay(string value)
{
txtCapacitance.Text = value;
}
//the thread
string msg = string.empty;
var th =new Thread(()=>{BeginInvoke(new updateTextboxDelegate(updateDisplay), msg); });
th.Start();
Hope that will work for you.
Upvotes: 0
Reputation: 117154
Updates to any UI element must be done on the UI-thread. You can certainly calculate your value on another thread, but you must use the .Invoke(...)
method of the control to perform the update.
Upvotes: 1