What must I do to make my methods awaitable?

B. Clay Shannon picture B. Clay Shannon · Nov 22, 2012 · Viewed 42k times · Source

How can I roll my own async awaitable methods?

I see that writing an async method is easy as pie in some cases:

private async Task TestGeo()
{
    Geolocator geo = new Geolocator();
    Geoposition pos = await geo.GetGeopositionAsync();
    double dLat = pos.Coordinate.Latitude;
    double dLong = pos.Coordinate.Latitude;
}

...but sadly also see that not just any method can be made async willy-nilly, though; to wit: this doesn't work:

private async Task TestAsyncAwait()
{
    int i = await TaSLs_Classes.TASLsUtils.GetZoomSettingForDistance(5);
}

...it stops me with the compile error, "Cannot await int"; a hint at design time similarly tells me, "type 'int' is not awaitable"

I also tried this with the same results:

    Task<int> i = await TaSLs_Classes.TASLsUtils.GetZoomSettingForDistance(5);

What must I do to make my methods awaitable?

UPDATE

As Linebacker and S. Cleary indicated (any relation to that cat who used to be on KNBR?), this works:

int i = await Task.Run(() => TaSLs_Classes.TASLsUtils.GetZoomSettingForDistance(5));

...that is to say, it compiles -- but it never "moves."

At runtime, it tells me I should "await" the CALL to TestAsyncAwait(), but if I do that, it doesn't compile at all...

Answer

Stephen Cleary picture Stephen Cleary · Nov 22, 2012

You only need to return an awaitable. Task/Task<TResult> is a common choice; Tasks can be created using Task.Run (to execute code on a background thread) or TaskCompletionSource<T> (to wrap an asynchronous event).

Read the Task-Based Asynchronous Pattern for more information.