Boolean ReceiveAsync(SocketAsyncEventArgs se, Boolean io) { if (Disposed) { Interlocked.Decrement(ref _RecvCount); se.TryDispose(); throw new ObjectDisposedException(GetType().Name); } var rs = false; try { // 开始新的监听 rs = OnReceiveAsync(se); } catch (Exception ex) { Interlocked.Decrement(ref _RecvCount); se.TryDispose(); if (!ex.IsDisposed()) { OnError("ReceiveAsync", ex); // 异常一般是网络错误,UDP不需要关闭 if (!io && ThrowException) throw; } return false; } // 如果当前就是异步线程,直接处理,否则需要开任务处理,不要占用主线程 if (!rs) { if (io) ProcessReceive(se); else Task.Factory.StartNew(() => ProcessReceive(se)); } return true; }
void ProcessReceive(SocketAsyncEventArgs se) { if (!Active) { se.TryDispose(); return; } // 判断成功失败 if (se.SocketError != SocketError.Success) { // 未被关闭Socket时,可以继续使用 //if (!se.IsNotClosed()) if (OnReceiveError(se)) { var ex = se.GetException(); if (ex != null) OnError("ReceiveAsync", ex); se.TryDispose(); return; } } else { // 拷贝走数据,参数要重复利用 var data = se.Buffer.ReadBytes(se.Offset, se.BytesTransferred); var ep = se.RemoteEndPoint as IPEndPoint; // 在用户线程池里面去处理数据 //Task.Factory.StartNew(() => OnReceive(data, ep)).LogException(ex => OnError("OnReceive", ex)); //ThreadPool.QueueUserWorkItem(s => OnReceive(data, ep)); // 直接在IO线程调用业务逻辑 try { // 估算完成时间,执行过长时提示 using (var tc = new TimeCost("{0}.OnReceive".F(GetType().Name), 1000)) { tc.Log = Log; OnReceive(data, ep); } } catch (Exception ex) { if (!ex.IsDisposed()) OnError("OnReceive", ex); } } // 开始新的监听 if (Active && !Disposed) ReceiveAsync(se, true); else se.TryDispose(); }
void ProcessSend(SocketAsyncEventArgs se) { if (!Active) { se.TryDispose(); return; } // 判断成功失败 if (se.SocketError != SocketError.Success) { // 未被关闭Socket时,可以继续使用 //if (!se.IsNotClosed()) { var ex = se.GetException(); if (ex != null) OnError("SendAsync", ex); se.TryDispose(); //if (se.SocketError == SocketError.ConnectionReset) Dispose(); if (se.SocketError == SocketError.ConnectionReset) Close("SendAsync " + se.SocketError); return; } } // 发送新的数据 if (Interlocked.CompareExchange(ref _Sending, 0, 1) == 1) CheckSendQueue(true); }