一边听着一个COM端口跨线程操作无效线程、端口、边听、操作

由网友(凯莉你太丧天害理丶)分享简介:可能重复: 获得跨线程操作无效 跨线程操作无效 Possible Duplicate:Getting Cross-thread operation not validCross-thread operation not valid 我想听听COM端口,使我创造SerialPort.DataReceived事件新的...

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

Possible Duplicate: Getting Cross-thread operation not valid Cross-thread operation not valid

我想听听COM端口,使我创造SerialPort.DataReceived事件新的处理程序。道理很简单 - 我写的东西TextBox1中,preSS Button1的和我的文字应该表现出它自身的标签1。但是,我的应用程序并不需要运行,becouse它抛出'跨线程操作无效的错误。 我做了一些搜索,发现调用的对象 - 我怎么能在我的例子中使用它?为什么我需要包括调用逻辑?

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 + "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运行。为了解决这个问题,你需要调用制定者在正确的线程的文本。这是这样的一个样本:

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

如果您使用的是.NET Framework 2.0中,上面的动作&LT; T1,T2&GT; 委托不可用,所以你必须定义自己的一种:

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方法是忽略不计,所以我倾向于使用较短的形式,只是因为它是不太code写的。

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.