Recommended method signature when returning output from asynchronous method?
Asked Answered
A

1

14

I have one asynchronous method:

public async Task<BitmapSource> GetBitmapAsync(double[] pixels);

Let's say I also have this class:

public class PixelData
{
    public double[] Pixels { get; }
}

I now want to create a convenience method producing a BitmapSource output, using the asynchronous method above to do the work. I can come up with at least three approaches to do this, but it is not immediately obvious to me which one I should choose from an efficiency and reliability point of view.

Can someone advice; what are the advantages and drawbacks of each one of the following approaches?

Option A Create a synchronous method that returns the Result of the Task:

public BitmapSource GetBitmap(PixelData pixelData)
{
    return GetBitmapAsync(pixelData.Pixels).Result;
}

Option B Create a synchronous (or is it asynchronous?) method that returns Task<BitmapSource>:

public Task<BitmapSource> GetBitmap(PixelData pixelData)
{
    return GetBitmapAsync(pixelData.Pixels);
}

Option C Create an asynchronous method that explicitly uses await:

public async Task<BitmapSource> GetBitmapAsync(PixelData pixelData)
{
    return await GetBitmapAsync(pixelData.Pixels);
}
Aperient answered 8/8, 2012 at 8:2 Comment(7)
And you want to be able to call this convenience method asynchronously also? If so, from what I can see on the face of it the first two options won't achieve this, only the third will.Novena
Not necessarily (do I want to call the convenience method asynchronously), but if that is the most reliable/correct way to do it, then yes.Aperient
@AdamHouldsworth Sorry for my ignorance in this matter, but will Option B be handled as a synchronous method for certain? The fact that it returns a Task<BitmapSource>, is that irrelevant with respect to (a)synchronicity?Aperient
Actually I'm not entirely sure myself, you might be able to call it with await - though I haven't got VS2012 in front of me to double check.Novena
@AndersGustafsson, It will not run synchronously.Back
Thanks, @FilipEkberg. I just checked myself and realized that I have to await for Option B. It is thus asynchronous, even if it is not evident from the method signature.Aperient
Methods are not awaitable. Only types are awaitable, so you can await a Task regardless of whether it's returned from an async or non-async method.Demijohn
S
6

I think you're over-thinking this.

You've got a method that returns a type that happens to be a Task<T>. You want a method that takes a different type of parameter and passes through to the original method. So Option B is fine:

public Task<BitmapSource> GetBitmap(PixelData pixelData)
{
    return GetBitmapAsync(pixelData.Pixels);
}

The method should be called GetBitmapAsync though.

Option A would be the way to expose a synchronous ( blocking ) version of the method.

Option C doesn't actually achieve anything more than Option B.

Stablish answered 8/8, 2012 at 8:38 Comment(2)
Thanks, Nicholas! Is it even so that Option C is worse than Option B, in that it would add redundant asynchronous handling? Or are the two options equivalent internally?Aperient
Also, Option A can cause deadlocks. Stephen Toub has a good video on async performance, and he points out that Option C is not a good idea (for overhead reasons).Demijohn

© 2022 - 2024 — McMap. All rights reserved.