跨线程操作在侦听COM端口时无效 [英] Cross-thread operation not valid while listening to a COM port

查看:157
本文介绍了跨线程操作在侦听COM端口时无效的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


可能重复:

跨线程操作无效

跨线程操作无效

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

I am trying to listen to COM port so that I create new handler for SerialPort.DataReceived event. The logic is simple - I write something to TextBox1, press Button1 and my text should show it self in Label1. But my application don't want to run, becouse it throws 'Cross thread operation not valid' error. I did some searching and found Invoke object - how can I use it in my example? Why do I need to include Invoke logic?

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 + "\n\n" + 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 + "\n\n" + exception.Data;
        }
        finally
        {
            sp.Close();
        }
    }
}

}

推荐答案

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

My guess is that MyDataReceivedHandler is running on a different thread than the GUI. In order to fix that, you need to invoke the Text setters on the correct thread. This is a sample of doing so:

public void SetControlText(Control control, string text)
{
    if (this.InvokeRequired)
    {
        this.Invoke(new Action<Control,string>(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 + "\n\n" + exception.Data);
    }
    finally
    {
        sp.Close();
    }
}

如果您使用的是.NET Framework 2.0, 动作< T1,T2> 委托不可用,因此您必须定义自己的一个:

If you are using .NET Framework 2.0, the above Action<T1, T2> delegate is not available, so you will have to define your own one:

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中使用):

The SetControlText method can be made shorter (and even static) like this (this works in both 2.0 and 3.5):

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

然后你不需要检查 InvokeRequired ,但是另一方面,即使不需要,也会将代理包裹在代理中。我认为在这样的GUI方法中,这两者之间的任何性能差异都是可忽略的,所以我倾向于使用较短的形式,因为它的代码要少一些。

Then you don't need to do the check of InvokeRequired each time, but you will on the other hand wrap the call in a delegate even if it is not needed. I think that in a GUI method like this any performance difference between those two is neglectible so I tend to use the shorter form, simply because it is less code to write.

这篇关于跨线程操作在侦听COM端口时无效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆