简体   繁体   中英

Multithreading Errors in C#

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.

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

You should rather have a look at using BackgroundWorker Class

Have a look at

C# BackgroundWorker Tutorial .

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.

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM