示例#1
0
        internal Task <int> SendAsync(ArraySegment <byte> buffer, SocketFlags socketFlags, bool wrapExceptionsInIOExceptions)
        {
            // Validate the arguments.
            ValidateBuffer(buffer);

            // Get the SocketAsyncEventArgs instance to use for the operation.
            Int32TaskSocketAsyncEventArgs saea = RentSocketAsyncEventArgs(isReceive: false);

            if (saea == null)
            {
                // We couldn't get a cached instance, which means there's already a receive operation
                // happening on this socket.  Fall back to wrapping APM.
                var tcs = new TaskCompletionSource <int>(this);
                BeginSend(buffer.Array, buffer.Offset, buffer.Count, socketFlags, iar =>
                {
                    var innerTcs = (TaskCompletionSource <int>)iar.AsyncState;
                    try { innerTcs.TrySetResult(((Socket)innerTcs.Task.AsyncState).EndSend(iar)); }
                    catch (Exception e) { innerTcs.TrySetException(e); }
                }, tcs);
                return(tcs.Task);
            }

            // Configure the buffer.  We don't clear the buffers when returning the SAEA to the pool,
            // so as to minimize overhead if the same buffer is used for subsequent operations (which is likely).
            // But SAEA doesn't support having both a buffer and a buffer list configured, so clear out a buffer list
            // if there is one before we set the desired buffer.
            if (saea.BufferList != null)
            {
                saea.BufferList = null;
            }
            saea.SetBuffer(buffer.Array, buffer.Offset, buffer.Count);
            saea.SocketFlags = socketFlags;
            saea.WrapExceptionsInIOExceptions = wrapExceptionsInIOExceptions;

            // Initiate the send
            Task <int> t;

            if (!SendAsync(saea))
            {
                // The operation completed synchronously.  Get a task for it and return the SAEA for future use.
                t = saea.SocketError == SocketError.Success ?
                    GetSuccessTask(saea) :
                    Task.FromException <int>(GetException(saea.SocketError, wrapExceptionsInIOExceptions));
                ReturnSocketAsyncEventArgs(saea, isReceive: false);
            }
            else
            {
                // The operation completed asynchronously.  Get the task for the operation,
                // with appropriate synchronization to coordinate with the async callback
                // that'll be completing the task.
                t = saea.GetTaskSafe();
            }
            return(t);
        }
示例#2
0
        /// <summary>Completes the SocketAsyncEventArg's Task with the result of the send or receive, and returns it to the specified pool.</summary>
        private static void CompleteSendReceive(Int32TaskSocketAsyncEventArgs saea, bool isReceive)
        {
            // Synchronize with the initiating thread accessing the task from the builder.
            saea.GetTaskSafe();

            // Pull the relevant state off of the SAEA and only then return it to the pool.
            Socket s = (Socket)saea.UserToken;
            AsyncTaskMethodBuilder <int> builder = saea.Builder;
            SocketError error                        = saea.SocketError;
            int         bytesTransferred             = saea.BytesTransferred;
            bool        wrapExceptionsInIOExceptions = saea.WrapExceptionsInIOExceptions;

            s.ReturnSocketAsyncEventArgs(saea, isReceive);

            // Complete the builder/task with the results.
            if (error == SocketError.Success)
            {
                builder.SetResult(bytesTransferred);
            }
            else
            {
                builder.SetException(GetException(error, wrapExceptionsInIOExceptions));
            }
        }