0
0
CsharpComparisonBeginner · 4 min read

Task vs void in async in C#: Key Differences and When to Use

In C#, async methods usually return Task to allow awaiting and proper error handling, while async void methods are used mainly for event handlers where no result or awaiting is needed. Using Task is preferred for most async methods because it supports waiting and catching exceptions.
⚖️

Quick Comparison

Here is a quick side-by-side comparison of async Task and async void methods in C#.

Factorasync Taskasync void
Return typeTaskvoid
Can be awaitedYesNo
Error handlingExceptions can be caught by callerExceptions crash app if unhandled
Use caseGeneral async methodsEvent handlers only
Allows compositionYes, can be combined with other tasksNo
Compiler supportSupports async state machineSupports async state machine
⚖️

Key Differences

async Task methods return a Task object that represents the ongoing operation. This allows the caller to await the method, pause execution until it completes, and catch any exceptions it throws. This makes async Task the preferred pattern for most asynchronous methods.

In contrast, async void methods do not return a Task and cannot be awaited. They are primarily designed for event handlers where the method signature requires void. Because they cannot be awaited, exceptions thrown inside async void methods cannot be caught by the caller and will crash the application if unhandled.

Using async void outside of event handlers is discouraged because it breaks the normal async flow and error handling. Meanwhile, async Task methods integrate well with the async/await pattern, enabling better control and composition of asynchronous code.

⚖️

Code Comparison

csharp
using System;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        try
        {
            await DoWorkAsync();
            Console.WriteLine("Work completed successfully.");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Caught exception: {ex.Message}");
        }
    }

    static async Task DoWorkAsync()
    {
        await Task.Delay(500);
        throw new InvalidOperationException("Something went wrong in Task method.");
    }
}
Output
Caught exception: Something went wrong in Task method.
↔️

async void Equivalent

csharp
using System;
using System.Threading.Tasks;

class Program
{
    static void Main()
    {
        try
        {
            DoWorkAsyncVoid();
            // No await possible here
            Console.WriteLine("Work started.");
            Task.Delay(1000).Wait(); // Wait to see output
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Caught exception: {ex.Message}");
        }
    }

    static async void DoWorkAsyncVoid()
    {
        await Task.Delay(500);
        throw new InvalidOperationException("Something went wrong in void method.");
    }
}
Output
Work started. Unhandled exception. System.InvalidOperationException: Something went wrong in void method.
🎯

When to Use Which

Choose async Task for almost all asynchronous methods because it allows callers to await the operation and handle exceptions properly. This makes your code more reliable and easier to maintain.

Use async void only for event handlers where the method signature requires void. Avoid using async void for general async methods as it prevents proper error handling and chaining.

Key Takeaways

async Task methods support awaiting and proper exception handling.
async void methods are only for event handlers and cannot be awaited.
Avoid async void for general async code to prevent unhandled exceptions.
Use async Task to compose and chain asynchronous operations safely.
Exceptions in async void methods crash the app if not caught globally.