![](/img/trans.png)
[英]After FileSystemWatcher fires - Thread Pool or Dedicated thread?
[英]thread call fires inconsistently
我是高级编程语言的初学者。 我正在尝试为串口创建一个WForms应用程序,即时通讯使用VS 2010 C#
我收到以下错误:
Cross-thread operation not valid: Control 'rtxtDataArea' accessed from a thread other than the thread it was created on.
这发生在这里:
private void ComPort_DataReceived_1(object sender, SerialDataReceivedEventArgs e)
{
recievedData = ComPort.ReadExisting(); //read all available data in the receiving buffer.
// Show in the terminal window
rtxtDataArea.ForeColor = Color.Green; // error ,
rtxtDataArea.AppendText(recievedData + "\n");
}
当我收到一些数据时,我试图改变文本框的颜色。 它会触发交叉线程错误。
问题是,当我尝试更改标签的颜色时,为什么它不会在此处触发相同的错误?
private void btnConnect_Click(object sender, EventArgs e)
{
if (ComPort.IsOpen)
{
disconnect();
}
else
{
connect();
rdText.ForeColor = Color.Blue;//ok, it works
}
}
; 这工作; 第一个没有。
为什么? ComPort_DataReceived_1与btnConnect_Click的性质不同吗? 或者是什么原因?
我已经阅读了很多关于线程的内容,但我理解我无法使用,有人可以给出一个直观的解释吗?
在winforms中,只有一个线程可以改变UI上的任何内容,如启用按钮,更改文本框等。通常这是UI线程。 这通常是你唯一的主题。
但是,如果您启动一个新线程,该线程可能希望更改UI。 如果此新线程触发表单收到的事件,则会发生这种情况。
每当您看到从其创建的线程以外的线程访问的消息时 ,您几乎可以肯定是这种情况。
解决此问题的最简单方法是使用Control.IsInvokeRequired和Control.Invoke函数。 这样做的模式如下。 以下函数更新myForm上的myButton
private void UpdateMyButton (MyType myParameter)
{
if (myButton.InvokeRequired)
{ // this is not the thread that created the button to update
this.Invoke(new MethodInvoker( () => this.UpdateMyButton(myParameter)));
// this will let the UI thread call this function with the same parameter.
}
else
{ // Now called by the UI thread: this thread may change myButton
myButton.Enabled = myParameter.ShouldButtonEnable;
myButton.Text = myParameter.ButtonText;
}
}
顺便说一句,如果你必须更新表单上的几个控件,你应该为每个控件检查InvokeRequired。 但是,由于它们通常由相同的UI线程创建,因此检查this.InvokeRequired就足够了。
Control.Invoke在调用完成后返回,因此在更新所有项目之后。 返回Invoke后,您可以使用UpdateMyButton的结果。
如果你不希望你的非ui线程等待UpdateMyButton的完成,请考虑使用Control.BeginInvoke:“嘿UI线程,只要你有时间,你可以为我更新UpdateMutton。当然在那种情况下你无法使用UpdateMyButton的结果
因为“DataReceived”在另一个线程而不是UI线程上运行。 您必须使用Invoke:
private void ComPort_DataReceived_1(object sender, SerialDataReceivedEventArgs e)
{
recievedData = ComPort.ReadExisting(); //read all available data in the receiving buffer.
if (InvokeRequired)
{
// If not on UI thread, then invoke
Invoke(new MethodInvoker(() =>
{
// Show in the terminal window
rtxtDataArea.ForeColor = Color.Green; // error ,
rtxtDataArea.AppendText(recievedData + "\n");
}));
}
else
{
// On UI thread, invoke not needed
// Show in the terminal window
rtxtDataArea.ForeColor = Color.Green; // error ,
rtxtDataArea.AppendText(recievedData + "\n");
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.