简体   繁体   中英

Implement async method synchronously

I have an interface which forces me to implement an (async) Task:

namespace Microsoft.Owin.Security.Infrastructure
{
    public interface IAuthenticationTokenProvider
    {
        ..
        Task CreateAsync(AuthenticationTokenCreateContext context);
        ..
    }
}

I want to implement this method, but I'm not awaiting anything. Although I have to await something or return some task, otherwise my code does not compile.:

public class MyImplementation: IAuthenticationTokenProvider
{
    public async Task CreateAsync(AuthenticationTokenCreateContext context) 
    {
        /// do something synchronously.

        await something here? ??
    }
}

My question is: How would I implement this method without doing something asynchronously? I've have found a couple of solutions (await task.Yield() , or await Task.Run(() => {})) , yet I can't fully understand what would be the correct implementation and why.

Just implement the method without awaiting:

public async Task<Foo> GetFooAsync()
{
    return new Foo();
}

It doesn't matter that you're not awaiting anything. It's not a requirement of an async method to await anything (although the compiler will warn you that you're not awaiting anything).

If you don't want the overhead of an aysnc method (there's a cost associated with the async "state machine" that might be undesirable), you could

public Task<Foo> GetFooAsync()
{
    return Task.FromResult(new Foo());
}

My solution is to return a Task that represents the result of an already executed synchronous method. That way you maintain the semantics an async method with regard to when the exception gets surfaced, without the overhead of the async state machine. Funny enough, I actually did this for the same reason on this same interface

I have an extension method:

    public static Task AsCompletedTask<T>(this Action<T> func, T arg)
    {
        var tcs = new TaskCompletionSource<VoidResult>();
        try
        {
            func(arg);
            tcs.SetResult(voidResult);
        }
        catch (Exception e)
        {
            tcs.SetException(e);
        };

        return tcs.Task;
    }

Which then I invoke via:

    public Task CreateAsync(AuthenticationTokenCreateContext context)
    {
        return ((Action<AuthenticationTokenCreateContext>)Create).AsCompletedTask(context);
    }

BTW, I hate that name. If anyone has a better suggestion, I'm all ears.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM