/// <summary> /// <para>Sends the data in <paramref name="sendData"/> to <see cref="EndPoint"/>. /// Calls <paramref name="resultAction"/> when response data has been recieved, /// the operation times-out, or the operation fails.</para> /// </summary> /// <param name="timeout">The time to wait, in milliseconds, before the operation times out.</param> /// <param name="sendData"> /// <para>The data to send. The pool item will be disposed, returned to the owning pool, /// automatically when it is no longer needed. So it is important that consumers do not /// access it after calling this method.</para> /// </param> /// <param name="resultAction"> /// <para>The method that will be called when the end point responds, /// the operation fails, or the operation times out.</para> /// </param> /// <exception cref="ArgumentNullException"> /// <para><paramref name="sendData"/> is <see langword="null"/>.</para> /// </exception> public void SendRoundTripAsync( int timeout, IPoolItem <MemoryStream> sendData, Action <RoundTripAsyncEventArgs> resultAction) { if (sendData == null) { throw new ArgumentNullException("sendData"); } var task = new AsyncSocketTask(this); task.SetEnumerator(GetSendEnumerator( timeout, sendData, OperationType.RoundTrip, resultAction, task.Callback)); task.Execute(true); }
/// <summary> /// <para>Sends the data in <paramref name="sendData"/> to the remote end point /// specified during construction. Calls <paramref name="resultAction"/> when all data /// has been sent. Please note that this only indicates that the server received the data /// and does not guarantee that data was processed.</para> /// </summary> /// <param name="timeout">The time to wait, in milliseconds, before the operation times out.</param> /// <param name="sendData"> /// <para>The data to send. The pool item will be disposed, returned to the owning pool, /// automatically when it is no longer needed. So it is important that consumers do not /// access it after calling this method.</para> /// </param> /// <param name="resultAction"> /// <para>The method that will be called when the host acknowledges that the data was /// received, the operation fails, or the operation times out.</para> /// </param> /// <exception cref="ArgumentNullException"> /// <para><paramref name="sendData"/> is <see langword="null"/>.</para> /// </exception> public void SendOneWayAsync( int timeout, IPoolItem <MemoryStream> sendData, Action <OneWayAsyncEventArgs> resultAction) { if (sendData == null) { throw new ArgumentNullException("sendData"); } _currentRequestId = Interlocked.Increment(ref _nextRequestId); var task = new AsyncSocketTask(this); task.SetEnumerator(GetSendEnumerator( timeout, sendData, OperationType.OneWay, resultAction, task.Callback)); task.Execute(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) { _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) { _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; }
/// <summary> /// <para>Sends the data in <paramref name="sendData"/> to <see cref="EndPoint"/>. /// Calls <paramref name="resultAction"/> when response data has been recieved, /// the operation times-out, or the operation fails.</para> /// </summary> /// <param name="timeout">The time to wait, in milliseconds, before the operation times out.</param> /// <param name="sendData"> /// <para>The data to send. The pool item will be disposed, returned to the owning pool, /// automatically when it is no longer needed. So it is important that consumers do not /// access it after calling this method.</para> /// </param> /// <param name="resultAction"> /// <para>The method that will be called when the end point responds, /// the operation fails, or the operation times out.</para> /// </param> /// <exception cref="ArgumentNullException"> /// <para><paramref name="sendData"/> is <see langword="null"/>.</para> /// </exception> public void SendRoundTripAsync( int timeout, IPoolItem<MemoryStream> sendData, Action<RoundTripAsyncEventArgs> resultAction) { if (sendData == null) throw new ArgumentNullException("sendData"); var task = new AsyncSocketTask(this); task.SetEnumerator(GetSendEnumerator( timeout, sendData, OperationType.RoundTrip, resultAction, task.Callback)); task.Execute(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; }