예제 #1
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 CompleteAccept(Socket s, TaskSocketAsyncEventArgs <Socket> saea)
        {
            // Pull the relevant state off of the SAEA
            SocketError error        = saea.SocketError;
            Socket?     acceptSocket = saea.AcceptSocket;

            // Synchronize with the initiating thread. If the synchronous caller already got what
            // it needs from the SAEA, then we can return it to the pool now. Otherwise, it'll be
            // responsible for returning it once it's gotten what it needs from it.
            bool responsibleForReturningToPool;
            AsyncTaskMethodBuilder <Socket> builder = saea.GetCompletionResponsibility(out responsibleForReturningToPool);

            if (responsibleForReturningToPool)
            {
                s.ReturnSocketAsyncEventArgs(saea);
            }

            // Complete the builder/task with the results.
            if (error == SocketError.Success)
            {
                builder.SetResult(acceptSocket !);
            }
            else
            {
                builder.SetException(GetException(error));
            }
        }
예제 #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(Socket s, TaskSocketAsyncEventArgs <int> saea, bool isReceive)
        {
            // Pull the relevant state off of the SAEA
            SocketError error                        = saea.SocketError;
            int         bytesTransferred             = saea.BytesTransferred;
            bool        wrapExceptionsInIOExceptions = saea._wrapExceptionsInIOExceptions;

            // Synchronize with the initiating thread. If the synchronous caller already got what
            // it needs from the SAEA, then we can return it to the pool now. Otherwise, it'll be
            // responsible for returning it once it's gotten what it needs from it.
            bool responsibleForReturningToPool;
            AsyncTaskMethodBuilder <int> builder = saea.GetCompletionResponsibility(out responsibleForReturningToPool);

            if (responsibleForReturningToPool)
            {
                s.ReturnSocketAsyncEventArgs(saea, isReceive);
            }

            // Complete the builder/task with the results.
            if (error == SocketError.Success)
            {
                builder.SetResult(bytesTransferred);
            }
            else
            {
                builder.SetException(GetException(error, wrapExceptionsInIOExceptions));
            }
        }
예제 #3
0
        /// <summary>Gets a task to represent the operation.</summary>
        /// <param name="pending">true if the operation completes asynchronously; false if it completed synchronously.</param>
        /// <param name="saea">The event args instance used with the operation.</param>
        /// <param name="fromNetworkStream">
        /// true if the request is coming from NetworkStream, which has special semantics for
        /// exceptions and cached tasks; otherwise, false.
        /// </param>
        /// <param name="isReceive">true if this is a receive; false if this is a send.</param>
        private Task <int> GetTaskForSendReceive(bool pending, TaskSocketAsyncEventArgs <int> saea, bool fromNetworkStream, bool isReceive)
        {
            Task <int> t;

            if (pending)
            {
                // The operation is completing asynchronously (it may have already completed).
                // Get the task for the operation, with appropriate synchronization to coordinate
                // with the async callback that'll be completing the task.
                bool responsibleForReturningToPool;
                t = saea.GetCompletionResponsibility(out responsibleForReturningToPool).Task;
                if (responsibleForReturningToPool)
                {
                    // We're responsible for returning it only if the callback has already been invoked
                    // and gotten what it needs from the SAEA; otherwise, the callback will return it.
                    ReturnSocketAsyncEventArgs(saea, isReceive);
                }
            }
            else
            {
                // The operation completed synchronously.  Get a task for it.
                if (saea.SocketError == SocketError.Success)
                {
                    // Get the number of bytes successfully received/sent.
                    int bytesTransferred = saea.BytesTransferred;

                    // For zero bytes transferred, we can return our cached 0 task.
                    // We can also do so if the request came from network stream and is a send,
                    // as for that we can return any value because it returns a non-generic Task.
                    if (bytesTransferred == 0 || (fromNetworkStream & !isReceive))
                    {
                        t = s_zeroTask;
                    }
                    else
                    {
                        // Otherwise, create a new task for this result value.
                        t = Task.FromResult(bytesTransferred);
                    }
                }
                else
                {
                    t = Task.FromException <int>(GetException(saea.SocketError, wrapExceptionsInIOExceptions: fromNetworkStream));
                }

                // There won't be a callback, and we're done with the SAEA, so return it to the pool.
                ReturnSocketAsyncEventArgs(saea, isReceive);
            }

            return(t);
        }