22

Let's just go ahead and say I have the following function:

public class Test
{
    public async Task Finalize()
    {
        // We don't need this in this class, so empty body
    }

    /*
     * Additional methods snipped
     */
}

While this works just fine, I will get a compiler warning saying:

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

What would be the best way to circumvent this warning without modifying the method too much? In this case, I'm not able to throw an exception, since the method will get called, but absolutely nothing is bound to happen at this point, since the class I'm talking about has nothing to finalize.


5 답변


13

You can put the following directive on the file(s):

#pragma warning disable 1998

However, I'd recommend leaving the warning alone, and taking its advice. It's a warning for a good reason ;)

EDIT: if you want to disable the warning for just one method, you can do this:

#pragma warning disable 1998
async Task Foo() {}
#pragma warning restore 1998


  • Wouldn't this disable all compiler warnings related to this issue, not just from one function? - Eisenhorn
  • that's right, you can use #pragma warning restore... let me edit. - Eren Ersönmez
  • This approach seems to work quite fine without adding an actual body. I'd mark both answers as correct, but you'll get the honor. Thanks! - Eisenhorn
  • Warnings are a sign that you have done something silly, hence the name. You should only disable a warning when you are 100% sure you have not done something silly. Since the code in the question is silly, disabling the warning has made things worse, as at least then it was silly code that warned you it was silly code when you went to compile it, and now it's silly code that doesn't do that. - Jon Hanna
  • @Jon I already have a warning in the answer, but I'm not sure if that was a good idea -- they seem to ignore it ;) - Eren Ersönmez

57

This way will prevent the compiler warning instead of muting it:

For anybody interested, if you ever need to circumvent such a compiler warning:

public async Task DoStuff
{
    // This method should stay empty
    // Following statement will prevent a compiler warning:
    await Task.FromResult(0);
}


  • Actual answer here. Pragma's are a last ditch way of getting around problems and are hard to maintain over time. Also comment the code and explain what your doing. - csaam
  • Yepp, my answer will prevent the warning itself, while Erens answer will only 'mute' the warnings. So mine is actually a little more correct, but I hate the idea of marking my own answers :P - Eisenhorn
  • Not really sure why you'd say that pragma's are a last ditch effort though, they do exactly what there are created for. There is a warning, you take heed of the warning and tell the compiler: "I know this is something to be careful about, but I really need this". I personally consider awaiting a fake task simply to get rid of a warning a hack, whereas using a pragma you are doing things exactly as they are intended. - Robba
  • There's no point creating a task, and then waiting on that task, so that you can then produce a task, that waits on that task. Just remove the async and the await from the above answer and it'll match the same signature and not generate a bunch of pointless code that won't be optimised away. - Jon Hanna
  • This post was written before .NET 4.6 which now offers Task.CompletedTask. - ZunTzu

32

This is a somewhat common problem when you have a synchronous (or noop) implementation for an asynchronous interface.

You can implement a Task-returning method without the async keyword by just returning a completed Task, as such:

public Task FinalizeAsync()
{
  return Task.FromResult(0);
}

However, this still allocates a Task every time it's called. If you find yourself doing this a lot, you may want to cache a completed Task instance. My AsyncEx library provides a number of task constants for this purpose:

public Task FinalizeAsync()
{
  return TaskConstants.Completed;
}

Finally, you may want to take a look at my blog post on asynchronous disposal for a couple of alternative approaches.


  • By far the best answer here, though if someone was to come along and add a comment pointing out that async is not part of the actual signature of a method, and therefore calling code and matching of interfaces won't be affected, that'd make it perfect ;) - Jon Hanna
  • This post was written before .NET 4.6 which now offers Task.CompletedTask. - ZunTzu
  • @JonHanna ah thanks for the clarification!! I hit this issue when declaring an empty virtual method that I wanted derived classes to be able to implement asynchronously, and didn't realize I could make the virtual method non-async. - Toby J
  • @Toby whether a method creates a Task by the async/await approach or another Task-creating method is up to the implementation. From the outside there's no difference, and that's all interfaces can insist on. - Jon Hanna

4

before .Net 4.6 we had to return a dummy value which we do not need to do this. However, now we can do it like this:

public async Task MyFunctionAsync()
{
    // Some works here...
    await Task.CompletedTask;
}


  • This answer is better than all. - Anoop H.N
  • I agree, it's a pity it's so new and likely to be overlooked. - Jessica Pennell

-1

Remove "async" and the warning goes away:

public class Test
{
    public void Finalize()
    {
        // We don't need this in this class, so empty body
    }
 }


  • You can get rid of the async, just return a Task, but changing the return type changes the method to external callers limiting the option of introducing async later. - Yishai

Related

Latest