Best practices

Other topics

Avoid async void

  • The only place where you can safely use async void is in event handlers. Consider the following code:

    private async Task<bool> SomeFuncAsync() {
      ...
      await ...
    }
    public void button1_Click(object sender,  EventArgs e) {
      var result = SomeFuncAsync().Result;
      SomeOtherFunc();
    }
    

    Once the async call completes, it waits for the SynchronizationContext to become available. However, the event handler holds on to the SynchronizationContext while it is waiting for SomeFuncAsync method to complete; thus causing a circular wait (deadlock).

    To fix this we need to modify the event handler to:

    public async void button1_Click(object sender,  EventArgs e) {
      var result = await SomeFuncAsync();
      SomeOtherFunc();
    }
    
  • Any exception thrown out of an async void method will be raised directly on the SynchronizationContext that was active when the async void method started.

    private async void SomeFuncAsync() {
      throw new InvalidOperationException();
    }
    public void SomeOtherFunc() {
      try {
        SomeFuncAsync();
      }
      catch (Exception ex) {
        Console.WriteLine(ex);
        throw;
      }
    }
    

    the exception is never caught by the catch block in SomeOtherFunc.

  • async void methods don’t provide an easy way to notify the calling code that they’ve completed

  • async void methods are difficult to test. MSTest asynchronous testing support only works for async methods returning Task or Task<T>.

Contributors

Topic Id: 9055

Example Ids: 28119

This site is not affiliated with any of the contributors.