private IEnumerator <bool> GetSendEnumerator( int timeout, IPoolItem <MemoryStream> sendData, OperationType type, Delegate resultAction, ParameterlessDelegate callback) { ValidateSocketForUse(); _sendData = sendData; _operationType = type; if (_operationType == OperationType.OneWay) { _oneWayResultAction = (Action <OneWayAsyncEventArgs>)resultAction; } else if (_operationType == OperationType.RoundTrip) { _roundTripResultAction = (Action <RoundTripAsyncEventArgs>)resultAction; _responseData = AsyncSocketClient.MemoryPool.Borrow(); } else { string message = string.Format("Unexpected operation type '{0}'", type); Debug.Fail(message); SetError(new InvalidOperationException(message)); yield break; } _socketArgs.UserToken = callback; if (_state == State.Uninitialized) { _state = State.Connecting; var connectTimeoutHandle = TaskMonitor.RegisterMonitor(_connectTimeout, _timeoutHandler, null); if (_socket.ConnectAsync(_socketArgs)) { yield return(false); } if (!connectTimeoutHandle.TrySetComplete()) { SetError(SocketError.TimedOut); yield break; } if (!ValidateCompletedEvent(_socketArgs, SocketAsyncOperation.Connect)) { yield break; } _state = State.Connected; ThreadPool.UnsafeQueueUserWorkItem(o => { var target = (SocketChannel)o; var task = new AsyncSocketTask(this); task.SetEnumerator(target.GetReceiveEnumerator(task.Callback)); task.Execute(false); }, this); } Debug.Assert(_sendData != null, "_sendData was not set prior to starting the send enumerator."); _socketArgs.SetBuffer(_sendData.Item.GetBuffer(), (int)_sendData.Item.Position, (int)_sendData.Item.Length); _timeoutHandle = TaskMonitor.RegisterMonitor(timeout, _timeoutHandler, null); if (_socket.SendAsync(_socketArgs)) { yield return(false); } if (!ValidateCompletedEvent(_socketArgs, SocketAsyncOperation.Send)) { yield break; } _messageSent = true; }
private IEnumerator <bool> GetSendEnumerator( int timeout, IPoolItem <MemoryStream> sendData, OperationType type, Delegate resultAction, ParameterlessDelegate callback) { ValidateSocketForUse(); _sendData = sendData; _operationType = type; if (_operationType == OperationType.OneWay) { _oneWayResultAction = (Action <OneWayAsyncEventArgs>)resultAction; } else if (_operationType == OperationType.RoundTrip) { _roundTripResultAction = (Action <RoundTripAsyncEventArgs>)resultAction; _responseData = AsyncSocketClient.MemoryPool.Borrow(); } else { string message = string.Format("Unexpected operation type '{0}'", type); Debug.Fail(message); SetError(new InvalidOperationException(message)); yield break; } _socketArgs.UserToken = callback; if (_state == State.Uninitialized) { LogDebugStep("Connecting..."); _state = State.Connecting; var connectTimeoutHandle = TaskMonitor.RegisterMonitor(_connectTimeout, _timeoutHandler, null); if (_socket.ConnectAsync(_socketArgs)) { yield return(false); } if (!connectTimeoutHandle.TrySetComplete()) { LogDebugStep("Failed to set connection timeout handle complete."); SetError(SocketError.TimedOut); yield break; } if (!ValidateCompletedEvent(_socketArgs, SocketAsyncOperation.Connect)) { yield break; } _state = State.Connected; LogDebugStep("Connected."); ThreadPool.UnsafeQueueUserWorkItem(o => { var target = (SocketChannel)o; var task = new AsyncSocketTask(this); task.SetEnumerator(target.GetReceiveEnumerator(task.Callback)); task.Execute(false); }, this); } Debug.Assert(_sendData != null, "_sendData was not set prior to starting the send enumerator."); _socketArgs.SetBuffer(_sendData.Item.GetBuffer(), (int)_sendData.Item.Position, (int)_sendData.Item.Length); _timeoutHandle = TaskMonitor.RegisterMonitor(timeout, _timeoutHandler, null); // note - it seems this is necessary because of a bug in the SendAsync function // see - http://social.msdn.microsoft.com/Forums/en-IE/ncl/thread/40fe397c-b1da-428e-a355-ee5a6b0b4d2c Thread.MemoryBarrier(); if (_log.IsDebugEnabled) { LogDebugStep(string.Format("Sending {0:###,###,###,##0} bytes", _sendData.Item.Length - _sendData.Item.Position)); } if (_socket.SendAsync(_socketArgs)) { yield return(false); } if (!ValidateCompletedEvent(_socketArgs, SocketAsyncOperation.Send)) { yield break; } _messageSent = true; }