Is it OK to declare an async method as returning void to silence the CS4014 warning?

前端 未结 4 1899
南方客
南方客 2021-01-02 03:12

Visual Studio emits a warning for this code (\'because this call is not awaited, execution of the current method continues before the call is completed\').

s         


        
相关标签:
4条回答
  • 2021-01-02 03:16

    Is it OK to have a 'async void' method if the method is not designed to be awaitable in the first place and if no exception will be thrown?

    Although it may be "OK" to do so, I would still encourage you to make the method async Task. Even though you are a 100 percent sure this method won't throw, and isn't ment to be awaited, you never know how it might end up getting used. You're now fully aware of what the consequences of using async void are, but if there's a slight chance that someone might need to use this in the future, then you're better of putting a nice comment on why this Task isn't being awaited instead of going with the easy path of making this void.

    Don't let the compiler warnings worry you, I would say worry about the correctness and the effects this may have on your codebase.

    0 讨论(0)
  • 2021-01-02 03:25

    It's extremely rare to have a true fire-and-forget operation; that is, an operation where:

    • No one cares when it completes.
    • No one cares if it completes.
    • No one cares if it throws an exception.

    Particularly with the last of these; most so-called "fire-and-forget" operations are not actually fire-and-forget because some action needs to be taken if it doesn't succeed.

    That said, there are a few situations where a true fire-and-forget is applicable.

    I prefer to use async Task and avoid the compiler warning by assigning the task to an otherwise unused variable:

    var _ = FireAndForget();
    

    async Task methods are more reusable and testable than async void methods.

    However, I wouldn't throw a fit if a developer on my team just used async void instead.

    0 讨论(0)
  • 2021-01-02 03:32

    One potential problem point is that it will now be impossible to tell if the code threw an exception or not. So if you have unit tests in place to detect these, the unit tests will never work.

    Classic example from MSDN site:

    private async void ThrowExceptionAsync()
    {
      throw new InvalidOperationException();
    }
    public void AsyncVoidExceptions_CannotBeCaughtByCatch()
    {
      try
      {
        ThrowExceptionAsync();
      }
      catch (Exception)
      {
        // The exception is never caught here!
        throw;
      }
    }
    

    http://haacked.com/archive/2014/11/11/async-void-methods/

    https://msdn.microsoft.com/en-us/magazine/jj991977.aspx

    Instead of using async void, if this is a specific edge case, how about using pragma statements?

    #pragma warning disable CS-4014
    ... your code here ...
    #pragma warning restore CS-4014
    

    This way you can tune out the static noise.

    HTH...

    0 讨论(0)
  • 2021-01-02 03:37

    Sometimes you want to fire and forget, however you should always want to make it explicit for someone reading your code. I find the "_" notation not explicit enough, so here's how I do it, with an extension method:

    public static class TaskExtensions()
    {
        public static void InvokeAndIgnore(this Task fireAndForgetTask)
        {
            // deliberately do nothing; used to suppress warning
        }
    }
    

    You can use it as follows:

    worker.AttemptCloseAsync().InvokeAndIgnore();
    
    0 讨论(0)
提交回复
热议问题