Пример #1
0
        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;
        }
Пример #2
0
        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;
        }