BeginReceive 與endReceive 必須成對出現,如果BeginReceive沒有及時調用endReceive,可能會出現數據被從buffer中讀取二次,如果在下面這行代碼下面加入別的代碼
就會出現被處理二次的結果 如下
public void BeginReceive(SessionListner listner)
{
if (listner.State != TSessionState.Active)
{
return;
}
try
{
int bufferOffset = this.BufferManager.GetReceivevBufferOffset(m_bufferBlockIndex);
WorkSocket.BeginReceive(this.BufferManager.ReceiveBuffer, bufferOffset, this.BufferManager.ReceiveBufferSize, SocketFlags.None, this.EndReceiveDatagram, listner);
listner.Receive();
}
catch (Exception err) // 讀 Socket 異常,准備關閉該會話
{
listner.DisconnectType = TDisconnectType.Exception;
listner.State = TSessionState.Inactive;//這個客戶狀態不活動了
//說明發送端口被異常關閉了
this.OnSessionReceiveException(listner, err);
}
}
上面的 listner.Receive();處理緩存數據方法
然后再執行
private void EndReceiveDatagram(IAsyncResult iar)
{
SessionListner listner = (iar.AsyncState as SessionListner);
if (listner.State != TSessionState.Active)
{
return;
}
try
{
int cr = WorkSocket.EndReceive(iar);
Console.WriteLine(cr);
if (cr == 0)
{
listner.DisconnectType = TDisconnectType.Normal;
listner.State = TSessionState.Inactive;
//被關閉了,需要及時關閉
}
else
{
listner.LastSessionTime = DateTime.Now;
this.BufferManager.RealReceiveSize = cr;
this.BeginReceive(listner);
}
}
就出現被二次處理的問題,分析得出:1,在第一次讀取完就處理緩沖數據,2同時進入了EndReceiveDatagram方法,再一次時進入BeginReceive方法 ,但沒有處理完第一次緩存數據,就可能導致處理數據不正確。
需要改成:EndReceiveDatagram中處理數據
else { listner.LastSessionTime = DateTime.Now; this.BufferManager.RealReceiveSize = cr; listner.Receive(); this.BeginReceive(listner); }
總結:處理數據永遠需要放到接收后處理,BeginReceive在永遠不斷的起線程,而endReceive在不斷的幫它完成回收和結束工作。在Begin中下面放執行代碼有可能有一定問題。也就是在沒有end的時候,沒有阻塞后,再操作共享變量有一定問題,所以begin與end同時操作共享對象或變量時時一定要end之后。無論socket還是一般的異步委托方法。
