How to configure DatagramSocket.MessageReceived for use with async / wait?

I would like to wrap the following datagram socket operation using TPL in order to clear the API so that it works well with asyncand awaithow the class does StreamSocket.

public static async Task<bool> TestAsync(HostName hostName, string serviceName, byte[] data)
{
    var tcs = new TaskCompletionSource<bool>();
    var socket = new DatagramSocket();
    socket.MessageReceived += (sender, e) =>
    {
        var status = false; // Status value somehow derived from e etc.
        tcs.SetResult(status);
    };
    await socket.ConnectAsync(hostName, serviceName);
    var stream = await socket.GetOutputStreamAsync();
    var writer = new DataWriter(stream);
    writer.WriteBytes(data);
    await writer.StoreAsync();
    return tcs.Task;
}

The sticking point is an event MessageReceivedthat turns the class DatagramSocketinto a strange target for an asynchronous event template and a new template async. In any case, TaskCompletionSource<T>it allows me to adapt the handler to the latter so that it is not too scary.

This seems to work very well if the endpoint never returns any data. The task associated with the handler MessageReceivednever completes, and therefore the task returned from TestAsyncnever completes.

- ? , CancellationToken , ? , , "" Task.Delay, - , :

public static async Task<bool> CancellableTimeoutableTestAsync(HostName hostName, string serviceName, byte[] data, CancellationToken userToken, int timeout)
{
    var tcs = new TaskCompletionSource<bool>();
    var socket = new DatagramSocket();
    socket.MessageReceived += (sender, e) =>
    {
        var status = false; // Status value somehow derived from e etc.
        tcs.SetResult(status);
    };
    await socket.ConnectAsync(hostName, serviceName);
    var stream = await socket.GetOutputStreamAsync();
    var writer = new DataWriter(stream);
    writer.WriteBytes(data);
    await writer.StoreAsync();

    var delayTask = Task.Delay(timeout, userToken);
    var t1 = delayTask.ContinueWith(t => { /* Do something to tcs to indicate timeout */ }, TaskContinuationOptions.OnlyOnRanToCompletion);
    var t2 = delayTask.ContinueWith(t => { tcs.SetCanceled(); }, TaskContinuationOptions.OnlyOnCanceled);

    return tcs.Task;
}

, MessageReceived. , , . , .

: , API DatagramSocket ? , IAsyncAction WinRT TPL - EAP, , API, , UDP, , ConnectAsync . .

+5
2

-, , DatagramSocket - UDP. , . WinRT IAsyncAction ( .Net Task) pull, (, ReadNextDatagramAsync()). TCP, , , , . UDP push ( WinRT .Net) .

, Connect 100% - , , , , StreamSocket. , .

@usr, . , , , , , .

, : , Task MessageReceived , , Delay(), ( , , Delay()), , CancellationToken, ( , Register() (ab), Delay()).

, , . : Try TaskCompletionSource (, TrySetResult()).

+2

: tcs.TrySetCancelled() . cancellationToken.Register , . , .

. , .

0

All Articles