c# Invoke和 BeginInvoke的区别 ,在SerialPort 中使用方式

vs中有一个控件SerialPort ,可以实现串口信息的收发,一般我们对于在串口收到的信息只是做读取,不会在其中加入function或者其他操作,可是如果让你加入一个变量or function,你怎么办?要知道SerialPort 的DataReceive 是运行在辅助线程上面的,这里就要用到Invoke\BeginInvoke,下面我们分情况讨论:

首先大家先了解一下Invoke\BeginInvoke,给大家一个链接http://blog.163.com/kjpt126@126/blog/static/48940426200824103658846/,介绍的很好;

弄明白了Invoke\BeginInvoke的不同之后,我们开始看代码:

Open SerialPort 操作

private void buttonOpenCloseSerialPort_Click(object sender, EventArgs e)

{

//设置好端口,波特率

comm.PortName = comboPortName.Text;

comm.BaudRate = int.Parse(comboBaudrate.Text);

try

{comm.Open();}

catch(Exception ex)

{//捕获到异常信息,创建一个新的comm对象,之前的不能用了。

comm = new SerialPort();

//现实异常信息给客户。

MessageBox.Show(ex.Message);

}

Thread.Sleep(1000);

Function_A()//是否需要Function_B的结果

}

DataReceived 操作

void comm_DataReceived(object sender, SerialDataReceivedEventArgs e)

{

if (PClosing)

return;//如果正在关闭,忽略操作,直接返回,尽快的完成串口监听线程的一次循环

try

{

int n = comm.BytesToRead;

byte[] buf = new byte[n];

received_count += n;

comm.Read(buf, 0, n);

builder.Clear();

//因为要访问UI资源,需要使用invoke方式同步UI。

//因为要访问UI资源,需要使用Begininvoke方式异步UI。

this.Invoke((EventHandler)(delegate

{// 判断是否是显示为16进制

if (checkBoxHexView.Checked)

{//依次的拼接出16进制字符串

foreach (byte b in buf)

{builder.Append(b.ToString("X2") + " ");}

}

else{ //直接按ASCII规则转换成字符串

builder.Append(Encoding.ASCII.GetString(buf));

}

//追加的形式添加到文本框末端,并滚动到最后。

this.richTextBox.AppendText(builder.ToString());

}));

}

Function_B() // 注意,Function_B是在辅助线程上实现,当采用Invoke时,会被阻塞;采用BeginInvoke会直接执行,所以当Function_A想要调 用Function_B的结果时,我们需要Sleep()并且采用BeginInvoke

}

Function_A() // UI主线程

Function_B() // 辅助线程