Csharp/C#教程:侦听COM端口时跨线程操作无效分享


侦听COM端口时跨线程操作无效

可能重复:
使跨线程操作无效
跨线程操作无效

我正在尝试侦听COM端口,以便为SerialPort.DataReceived事件创建新的处理程序。 逻辑很简单 – 我写了一些东西给TextBox1,按下Button1,我的文本应该在Label1中显示它自己。 但我的应用程序不想运行,因为它抛出“交叉线程操作无效”错误。 我做了一些搜索并找到了Invoke对象 – 我如何在我的例子中使用它? 为什么我需要包含Invoke逻辑?

namespace WindowsApplication1 { public partial class Form1 : Form { SerialPort sp = new SerialPort(); public Form1() { InitializeComponent(); sp.DataReceived += MyDataReceivedHandler; } private void Form1_Load(object sender, EventArgs e) { } private void MyDataReceivedHandler(object sender, SerialDataReceivedEventArgs e) { try { //sp.PortName = "COM3"; //sp.Open(); Label1.Text = sp.ReadLine(); } catch (Exception exception) { RichTextBox1.Text = exception.Message + "nn" + exception.Data; } finally { sp.Close(); } } private void button1_Click(object sender, EventArgs e) { try { sp.PortName = "COM3"; sp.Open(); sp.WriteLine(TextBox1.Text); } catch (Exception exception) { RichTextBox1.Text = exception.Message + "nn" + exception.Data; } finally { sp.Close(); } } } 

}

我的猜测是MyDataReceivedHandler运行在与GUI不同的线程上。 为了解决这个问题,您需要在正确的线程上调用Text setter。 这是这样做的一个例子:

 public void SetControlText(Control control, string text) { if (this.InvokeRequired) { this.Invoke(new Action(SetControlText), new object[] { control, text }); } else { control.Text = text; } } private void MyDataReceivedHandler(object sender, SerialDataReceivedEventArgs e) { try { //sp.PortName = "COM3"; //sp.Open(); SetControlText(Label1, sp.ReadLine()); } catch (Exception exception) { SetControlText(RichTextBox1, exception.Message + "nn" + exception.Data); } finally { sp.Close(); } } 

如果您使用的是.NET Framework 2.0,则上述Action委托不可用,因此您必须定义自己的委托:

 private delegate void SetControlTextHandler(Control control, string text); public void SetControlText(Control control, string text) { if (this.InvokeRequired) { this.Invoke(new SetControlTextHandler(SetControlText), new object[] { control, text }); } else { control.Text = text; } } 

SetControlText方法可以像这样更短(甚至是静态)(这适用于2.0和3.5):

 public static void SetControlText(Control control, string text) { ´control.Invoke((MethodInvoker)delegate { control.Text = text; }); } 

然后,您不需要每次都检查InvokeRequired ,但另一方面,即使不需要,您也将在委托中包装调用。 我认为在这样的GUI方法中,这两者之间的任何性能差异都是可以忽略的,所以我倾向于使用较短的forms,因为它写的代码较少。

每当从与其创建的线程不同的线程访问UI控件时,您还可以执行以下操作:

(.NET 3.5)

 myControl.BeginInvoke(new MethodInvoker( () => myControl.whatever = whatever; )); 

或(.NET 2.0)

 myControl.BeginInvoke(new MethodInvoker( delegate { myControl.whatever = whatever; )); 

编辑>有时使用Invoke进行长时间运行操作可以/仍将挂起ui,使用BeginInvoke显然异步执行该操作,并且ui不会挂起。

上述就是C#学习教程:侦听COM端口时跨线程操作无效分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/cdevelopment/961441.html

(0)
上一篇 2021年11月26日
下一篇 2021年11月26日

精彩推荐