Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert this code to async await?

I have lots of code like this:

        var feed = new DataFeed(host, port);
        feed.OnConnected += (conn) =>
        {
            feed.BeginLogin(user, pass);
        };
        feed.OnReady += (f) =>
        {
             //Now I'm ready to do stuff.
        };

        feed.BeginConnect();

As you can see, I use the usual way of doing async operations. how do I change this code to use async await? Preferably something like this:

public async void InitConnection()
{
    await feed.BeginConnect();
    await feed.BeginLogin(user, pass);

    //Now I'm ready
}
like image 330
nakiya Avatar asked Jun 12 '14 07:06

nakiya


1 Answers

You can use TaskCompletionSource<T> to wrap your EAP (event-based async pattern) into Tasks. It's not clear how you handle errors and cancel operations in your DataFeed class, so you will need to modify this code and add error handling (sample):

private Task ConnectAsync(DataFeed feed)
{
    var tcs = new TaskCompletionSource<object>();
    feed.OnConnected += _ => tcs.TrySetResult(null);
    feed.BeginConnect();
    return tcs.Task;
}

private Task LoginAsync(DataFeed feed, string user, string password)
{
    var tcs = new TaskCompletionSource<object>();
    feed.OnReady += _ => tcs.TrySetResult(null);
    feed.BeginLogin(user, pass);
    return tcs.Task;
}

Now you can use these methods:

public async void InitConnection()
{
    var feed = new DataFeed(host, port);
    await ConnectAsync(feed);
    await LoadAsync(feed, user, pass);
    //Now I'm ready
}

Note - you can move these async methods to DataFeed class. But if you can modify DataFeed, then better use TaskFactory.FromAsync to wrap APM API to Tasks.

Unfortunately there is no non-generic TaskCompletionSource which would return non-generic Task so, usually workaround is usage of Task<object>.

like image 169
Sergey Berezovskiy Avatar answered Nov 17 '22 22:11

Sergey Berezovskiy