/// <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)); } }
/// <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)); } }
/// <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); }