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() // 辅助线程