侦听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