2

In a WinRT project in C#, I used a DatagramSocket to send a request and wait with timeout for a response by subscribe to the messagereceived event. Like:

DatagramSocket socket=new DatagramSocket();
socket.MessageReceived+=(sender,args)=>{
    if(!timeout){
     ... do stuff to handle the msg
    }else{ ..discard the msg..}

}
...
//later I do something like socket.send() to send out the request and start the timer.

However I wonder if it's possible to to wrap all those calls in to a single awaitable async call so that I can do something like

SocketWrapper wrapper;
msg= await wrapper.RequestAndWaitForResponse(TimeSpan.FromSeconds(5));

So if no response come back, the async call will return a null after the timeout, and if there's a response, the async call will return right away with the message without waiting for the timeout.

John Saunders
  • 160,644
  • 26
  • 247
  • 397
malfoyjohn
  • 21
  • 2
  • Not exactly a duplicate but this might help: http://stackoverflow.com/questions/12858501/is-it-possible-to-await-an-event-instead-of-another-async-method – supertopi Feb 28 '15 at 12:55
  • @malfoyjohn: This is not how a `DatagramSocket` is normally used. Are you sure you want to create the socket just for a single send and reply? – Stephen Cleary Feb 28 '15 at 14:01
  • If you expect a single message this is straight-forward to do using the technique linked by supertopi. If you want to receive a stream of messages there will be some kind of buffering or hand-off between the push-producer and the pull-consumer. – usr Feb 28 '15 at 16:17
  • http://stackoverflow.com/questions/22783741/a-reusable-pattern-to-convert-event-into-task – SeBo Mar 31 '15 at 14:51

1 Answers1

2

The most simple solution to convert event based API to async calls is to use the TaskCompletionSource API.

This object will create a task that will be awaited until you call one of the SetResult/SetException/SetCanceled methods.

In you case, you can create a task that will complete when the MessageReceived event is received using the following code.

public Task<T> CreateMessageReceivedTask()
{
    var taskCompletionSource = new TaskCompletionSource<T>();
    var socket=new DatagramSocket();
    socket.MessageReceived += (sender,args) =>
    {
        if(!timeout)
        {
            // ... do stuff to handle the msg
            taskCompletionSource.SetResult(<your result>);
        }
        else
        {
            //..discard the msg..
            taskCompletionSource.SetException(new Exception("Failed"));
        }
    });
}
Vincent
  • 3,656
  • 1
  • 23
  • 32