今天在用SerialPort时候遇到咋关闭串口时候出现页面卡住不动的情况,通过查询一些资料终于找到解决方案了。第一次写这种技术贴,组织比较混乱,请见谅
在兔子党逍遥的文章http://blog.csdn.net/wuyazhe/article/details/5606276 中有分析道在SerialPort串口类关闭串口时候会陷入死锁,也提供一种用Application.DoEvent()解决;
但是此处的Application是System.Windows.Forms中的方法,而我在Bll层....这不是个好办法
通过查询Invoke,知晓Invoke是同步线程更新,在循环执行DataReceived中的线程时,插入串口的Close事件,因为Invoke的等待状态没有返回,导致死锁。
于是通过BeginInvoke异步执行更新,在While循环(见下面代码)中使用Lock,控制更新内容的顺序。
这里有关于Invoke和BeginInvoke的区别比较http://www.cnblogs.com/Rustle/articles/11301.aspx
这里只是部分主要代码
BLL层
private SerialPort sp = new SerialPort(){PortName = "COM3",DataBits = 8,StopBits = StopBits.One,Parity = Parity.None};
private object spObj = new object();
public void OpenPort(ProcessDelegate processModel)
{
dealThread = new Thread(new ThreadStart(StartPortMethod));
_interalPd = processModel;
dealThread.Start();
}
void StartPortMethod()
{
try
{
sp.Open();
sp.DataReceived += sp_DataReceived;
}
}
private void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
int len = sp.BytesToRead; //串口传过来的数据位数
var bBuff = new byte[len];
sp.Read(bBuff, 0, len); //把数据放进缓存
while (flagIndex < bBuff.Length)
{
//TODO:从缓存区获取一个数据包
//解析数据包
_dRModel = _rTrans.TransReceivedData(perBytePackage.ToArray());
//利用委托将model数据返回给UI
_interalPd(_dRModel);
}
}
}
public void ClosePort()
{
try
{
if (sp.IsOpen)
{
dealThread.Abort();
sp.DataReceived -= sp_DataReceived;
sp.Close();
}
}
catch (Exception)
{
throw;
}
}
UI层
/// <summary>
/// 接收从bll返回的数据并通过Invoke更新
/// </summary>
/// <param name="rdmodel"></param>
void UpdateReceivedData(ReceivedDataModel rdmodel)