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); } }
Aaron stainback
source share