How to create a wrapper to call async wait?

From what I can say, there is no built-in support (or extension extensions) for ConnectAsync / AcceptAsync / SendAsync / ReceiveAsync etc. How can I write my own shell that would be supported by an asynchronous wait mechanism. For example, my current code that processes ReceiveAsyn c is both an inline and a callback (which is specified in SocketAsyncEventArgs ):

 private void PostReceive(SocketAsyncEventArgs e) { e.SetBuffer(ReceiveBuffer.DataBuffer, ReceiveBuffer.Count, ReceiveBuffer.Remaining); e.Completed += Receive_Completed; // if ReceiveAsync returns false, then completion happened inline if (m_RemoteSocket.ReceiveAsync(e) == false) { Receive_Completed(this, e); } } 

.

 private void Receive_Completed(object sender, SocketAsyncEventArgs e) { e.Completed -= Receive_Completed; if (e.BytesTransferred == 0 || e.SocketError != SocketError.Success) { if (e.BytesTransferred > 0) { OnDataReceived(e); } Disconnect(e); return; } OnDataReceived(e); // // we do not push the SocketAsyncEventArgs back onto the pool, instead // we reuse it in the next receive call // PostReceive(e); } 
+7
source share
3 answers

The trick is to use TaskCompletionSource to handle this script.

I wrote about this. For more information, see Preparing Existing Code for Pending .

+3
source

You can also write a custom that I like in this situation. This is Microsoft's Stephen Tuub method. You can read more about this method here. http://blogs.msdn.com/b/pfxteam/archive/2011/12/15/10248293.aspx

Here is a custom view:

 public sealed class SocketAwaitable : INotifyCompletion { private readonly static Action SENTINEL = () => { }; internal bool m_wasCompleted; internal Action m_continuation; internal SocketAsyncEventArgs m_eventArgs; public SocketAwaitable(SocketAsyncEventArgs eventArgs) { if (eventArgs == null) throw new ArgumentNullException("eventArgs"); m_eventArgs = eventArgs; eventArgs.Completed += delegate { var prev = m_continuation ?? Interlocked.CompareExchange( ref m_continuation, SENTINEL, null); if (prev != null) prev(); }; } internal void Reset() { m_wasCompleted = false; m_continuation = null; } public SocketAwaitable GetAwaiter() { return this; } public bool IsCompleted { get { return m_wasCompleted; } } public void OnCompleted(Action continuation) { if (m_continuation == SENTINEL || Interlocked.CompareExchange( ref m_continuation, continuation, null) == SENTINEL) { Task.Run(continuation); } } public void GetResult() { if (m_eventArgs.SocketError != SocketError.Success) throw new SocketException((int)m_eventArgs.SocketError); } } 

Some extension methods that you need to add to the socket class and make it convenient:

 public static class SocketExtensions { public static SocketAwaitable ReceiveAsync(this Socket socket, SocketAwaitable awaitable) { awaitable.Reset(); if (!socket.ReceiveAsync(awaitable.m_eventArgs)) awaitable.m_wasCompleted = true; return awaitable; } public static SocketAwaitable SendAsync(this Socket socket, SocketAwaitable awaitable) { awaitable.Reset(); if (!socket.SendAsync(awaitable.m_eventArgs)) awaitable.m_wasCompleted = true; return awaitable; } // ... } 

Using:

  static async Task ReadAsync(Socket s) { // Reusable SocketAsyncEventArgs and awaitable wrapper var args = new SocketAsyncEventArgs(); args.SetBuffer(new byte[0x1000], 0, 0x1000); var awaitable = new SocketAwaitable(args); // Do processing, continually receiving from the socket while (true) { await s.ReceiveAsync(awaitable); int bytesRead = args.BytesTransferred; if (bytesRead <= 0) break; Console.WriteLine(bytesRead); } } 
+2
source

There is a wrapper for socket files in .NET 4.5. If you are using .NET 4, I would recommend using APM rather than an event-based asynchronous pattern. It is easier to convert to Task .

0
source

All Articles