超時分串口讀超時和串口寫超時,主要是讀超時,即ReadTimeout與Read方法之間的超時。下面談談他們之間的意義和實現。
Read方法是阻塞的,它一直在讀串口接收緩沖區中的數據,如果接收緩沖區有數據,Read方法則返回一個或多個字節數據;如果Read方法在等待ReadTimeout毫秒時間內,串口接收區一直沒有任何數據,則Read方法將甩ExceptionTimeout異常。注意,Read(outBuf, offset, count)阻塞讀取的不是非等到count個字節數據,而是當前接收緩沖區大於等於1小於等於count個字節數據,即只要有數據Read方法就立刻返回。
由於Read方法的阻塞性,所以我們必須防止(如串口物理斷開) Read永遠不返回,而導致程序卡死。方法有:
1. 設置ReadTimeout屬性為合理值,其默認值為-1,即Read永不可能因為ReadTimeout而超時返回。
2. 先判斷serialPort.BytesToRead大於0,再調用Read方法,則Read肯定會返回。
代碼段一:
int nStartTime = Environment.TickCount;
while(true)
{
int nNowTime = Environment.TickCount;
if(nNowTime – nStartTime > 360) //等待360ms
{
Console.WriteLine(“等待360ms后超時”);
break;
}
if(serialPort.BytesToRead > 35) //用戶業務數據包長度
{
int nLen = serialPort.Read(outBuf, 0, 35);
DealData(outBuf, nLen); //驗證合法包,然后處理業務
break;
}
//時間消耗在循環過程中,可在這加一行 Thread.Sleep(20);
}
代碼段二:
serialPort.ReadTimeout = 1000; //等待1000ms 初始化
//接收處理函數
try
{
int nLen = serialPort.Read(outBuf, 0, serialPort. BytesToRead); //如果接收區一直沒數據,時間消耗在這,等1000ms后甩TimeoutException異常
if(nLen > 0)
{
DealData(outBuf, nLen); //進全局數據隊列,然后分析隊列里的合法數據包
}
}
catch (TimeoutException ex)
{
Console.WriteLine("通信超時");
}