3

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.

6
  • If you don't await anything, your code should compile fine - it just won't actually be asynchronous. That may be okay if in your case there's basically a fast implementation that doesn't perform any IO - but otherwise you should really be doing things asynchronously... Commented Oct 6, 2016 at 11:01
  • If I do so I get a warning while compiling: "Async method lacks 'await' operators and will run synchronously". Why do I get this warning? Why does it matter? Commented Oct 6, 2016 at 11:11
  • Well the warning speaks for itself - you've got an async method, but it completes synchronously. In your case, that may be what you desire. It's hard to tell without knowing what the body of the CreateAsync method does. If it's always quick, then that's fine, and you can just suppress the warning for that bit of code. Commented Oct 6, 2016 at 11:13
  • Let's see if i get it right. In my case i would want to write the following code: public Task CreateAsync(AuthenticationTokenCreateContext context) { return Task.FromResult(0); } Because it is not asyncronous? Commented Oct 6, 2016 at 11:22
  • You could do, if you didn't actually want to do anything asynchronous. But we don't know whether running all your code synchronously is appropriate, because we don't know what that code is. And as hvd mentions in comments, that wouldn't work well in terms of exception handling - an async method would normally return a faulted task rather than throwing an exception, apart from possibly argument validation. Commented Oct 6, 2016 at 11:33

2 Answers 2

2

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());
}
Sign up to request clarification or add additional context in comments.

3 Comments

Instead of worrying about the cost (since that's probably a micro-optimisation), worry about the difference in effect if new Foo() throws an exception: in the async version, a task gets returned that indicates it did not complete successfully. In the other version, no task gets returned at all.
The problem is that i am not working with Task<T>, but with just a Task. So it's an async void. Thus it isn't anything to create a result from.
@ClarkKent Task<T> implements Task, so you can just return Task.FromResult(0) to satisfy a (non-generic) return type of Task. The "value" of the task just won't be used.
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.