45

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...

B. Clay Shannon-B. Crow Raven
  • 8,547
  • 144
  • 472
  • 862

4 Answers4

28

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.

Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810
18

Your method

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

should be written like this

private async Task TestAsyncAwait()
{
    Task<int> t = new Task<int>(() =>
    {
        return TaSLs_Classes.TASLsUtils.GetZoomSettingForDistance(5);
    });
    t.Start();
    await t;
}

If you need to return the int, replace the Task type:

private async Task<int> TestAsyncAwait()
{
    Task<int> t = new Task<int>(() =>
    {
        return TaSLs_Classes.TASLsUtils.GetZoomSettingForDistance(5);
    });
    t.Start();
    return await t;
}
Jeson Martajaya
  • 6,996
  • 7
  • 54
  • 56
3
var something = Task<int>.Factory.StartNew(() => 0);
something.Wait();
int number = something.Result;
p3n
  • 79
  • 5
1

You need to either consume the awaited return or return Task<Type of await call>

  1. private async Task<Geoposition> TestGeo()
    {
        Geolocator geo = new Geolocator();
        return await geo.GetGeopositionAsync();
    }
    
  2. private async Task<int> TestAsyncAwait()
    {
        return await TaSLs_Classes.TASLsUtils.GetZoomSettingForDistance(5);
    }
    
svick
  • 236,525
  • 50
  • 385
  • 514
Mayank
  • 8,777
  • 4
  • 35
  • 60