== Why is this an issue? An https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/async[`async`] method with a `void` return type does not follow the https://learn.microsoft.com/en-us/dotnet/csharp/asynchronous-programming/task-asynchronous-programming-model[task asynchronous programming (TAP)] model since the return type should be https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task[`Task`] or https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task-1[`Task`] Doing so prevents control over the https://learn.microsoft.com/en-us/dotnet/csharp/asynchronous-programming/async-scenarios[asynchronous execution], such as: * waiting for the execution to complete * catching any exception that might occur during execution * testing execution behavior === Exceptions * Methods with the https://learn.microsoft.com/en-us/dotnet/api/system.eventhandler[`EventHandler`] delegate signature. + Using `void` for `EventHandler` is compliant with the TAP model. + [source,csharp] ---- public async void button1_Click(object sender, EventArgs e) { await DoSomethingAsync(); } ---- * Methods name matching ``++On[A-Z]\w*++`` pattern. + Some frameworks may not use the same `EventHandler` method signature + [source,csharp] ---- public async void OnClick(EventContext data) { await DoSomethingAsync(); } ---- == How to fix it Update the return type of the method from `void` to `Task`. === Code examples ==== Noncompliant code example [source,csharp,diff-id=1,diff-type=noncompliant] ---- private async void ThrowExceptionAsync() // Noncompliant: async method return type is 'void' { throw new InvalidOperationException(); } public void Method() { try { ThrowExceptionAsync(); } catch (Exception) { // The exception is never caught here throw; } } ---- ==== Compliant solution [source,csharp,diff-id=1,diff-type=compliant] ---- private async Task ThrowExceptionAsync() // Compliant: async method return type is 'Task' { throw new InvalidOperationException(); } public void Method() { try { await ThrowExceptionAsync(); } catch (Exception) { // The exception is caught here throw; } } ---- == Resources === Documentation * Microsoft Learn - https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/async[`async` (C# Reference)] * Microsoft Learn - https://learn.microsoft.com/en-us/dotnet/csharp/asynchronous-programming/async-scenarios[Asynchronous programming] * Microsoft Learn - https://learn.microsoft.com/en-us/dotnet/csharp/asynchronous-programming/task-asynchronous-programming-model[Task asynchronous programming model] * Microsoft Learn - https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task[`Task` Class] * Microsoft Learn - https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task-1[`Task` Class] * Microsoft Learn - https://learn.microsoft.com/en-us/dotnet/api/system.eventhandler[`EventHandler` Delegate] ifdef::env-github,rspecator-view[] ''' == Implementation Specification (visible only on this page) === Message Return "Task" instead. ''' == Comments And Links (visible only on this page) === on 30 Jun 2015, 13:36:13 Ann Campbell wrote: \[~tamas.vajk] I don't understand the code snippets. The `async Task` method doesn't return anything. Also, could you morph the Noncompliant Example into a Compliant Solution, please? === on 1 Jul 2015, 07:10:48 Tamas Vajk wrote: \[~ann.campbell.2] I added the compliant solution. A method with `async` keyword returning a `Task` is like a non `async` method with `void` return type. Similarly in an `async Task` method we can return a simple `int`. (\https://msdn.microsoft.com/en-us/library/hh524395.aspx) === on 1 Jul 2015, 11:31:53 Ann Campbell wrote: \[~tamas.vajk] that makes me wonder if we should generalize this rule to catch _any_ `async` method that does not return a `Task`...? === on 1 Jul 2015, 11:49:54 Tamas Vajk wrote: \[~ann.campbell.2] That's a compiler error (CS1983, _The return type of async must be void, Task or Task_). === on 1 Jul 2015, 11:59:39 Ann Campbell wrote: Okay, thanks [~tamas.vajk] endif::env-github,rspecator-view[]