2010-04-08 79 views
6

我正在尝试更新文本框。我认为我的线程代码可以解决这个问题,但它不会。有人能帮忙吗?C中的多线程错误#

new Thread((ThreadStart)delegate { txtCapacitance.Text = Math.Round(capacitance, 3).ToString(); }).Start(); 

提供了以下错误:这一切都是由一个dataReceived功能每当接收USB数据被称为启动

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

注意。

回答

4

你还是看看使用BackgroundWorker Class

看一看

C# BackgroundWorker Tutorial

+0

这不会解决问题。后台工作人员仍然在与UI线程不同的线程上运行。 – 2010-04-08 04:31:58

+0

@Marcelo Cantos,你看过文档吗? *您必须小心,不要操作DoWork事件处理程序中的任何用户界面对象。相反,通过ProgressChanged和RunWorkerCompleted事件与用户界面进行通信。* – 2010-04-08 04:34:27

+0

你是对的;我错了;我很抱歉。我把它和普通的线程池混淆了。 – 2010-04-08 08:54:09

6

UI对象只能从UI线程中调用。这可以通过控制的Invoke方法来实现:

txtCapacitance.Invoke((Action)(() => { txtCapacitance.Text = Math.Round(capacitance, 3).ToString(); })); 
+0

我收到此错误: 无法将lambda表达式转换为键入'System.Delegate',因为它不是委托类型 – Adam 2010-04-08 04:33:45

+0

对不起,您必须进行转换。我修复了它。 – 2010-04-08 10:05:39

1

更新任何UI元素必须在UI线程上完成。您当然可以在另一个线程上计算您的值,但您必须使用控件的.Invoke(...)方法来执行更新。

0

试试这个

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

希望这会为你工作。

0

您需要确保您从创建它的同一个线程更新textBox。

为此自己创建的类帮手喜欢这一点,并使用这个扩展,而不是使用常规方式(这里有几个扩展我为我自己做的,但一个有趣的,你是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; 
     } 
    } 

} 

然后你这样使用它:txtCapacitance.changeText("new text");