async void là "fire-and-forget": không trả về Task, không thể await, exception không bị capture vào Task. Exception sẽ ném lên SynchronizationContext (UI thread) hoặc ThreadPool -> crash ứng dụng nếu không xử lý.
Ba kiểu trả về async
| Return Type | Exception Handling | Dùng khi |
|---|---|---|
Task | Wrap trong Task, bắt bằng try/catch await | Async method không trả giá trị (khuyến nghị thay void) |
Task<T> | Wrap trong Task, bắt bằng try/catch await | Async method trả giá trị |
void | Không capture, ném lên SyncContext | Event handler, top-level entry (Main) |
Ví dụ: Bắt exception từ async Task (Đúng)
static async Task Main()
{
try
{
await DoSomethingAsync();
}
catch (ArgumentNullException ex)
{
Console.WriteLine($"Caught: {ex.Message}");
}
}
static async Task DoSomethingAsync()
{
await FooAsync();
}
static async Task FooAsync()
{
throw new ArgumentNullException("demo");
}
Vấn đề với async void
// KHÔNG THỂ BẮT EXCEPTION TỪ NGOÀI
static async void BadAsyncVoid()
{
throw new InvalidOperationException("Boom!");
}
static void Main()
{
try
{
BadAsyncVoid(); // Không await được
Console.WriteLine("After call"); // Chạy tiếp, exception ném sau
}
catch (Exception ex)
{
Console.WriteLine("Never caught!"); // Không bao giờ chạy
}
// Ứng dụng crash sau vài giây (unobserved exception)
}
Giải pháp cho Event Handler (bắt buộc async void)
// WinForms / WPF / Blazor event handler
private async void Button_Click(object sender, EventArgs e)
{
try
{
await RiskyOperationAsync();
}
catch (Exception ex)
{
// Xử lý tại chỗ: log, show message, v.v.
MessageBox.Show($"Error: {ex.Message}");
// Hoặc log to ILogger
}
}
Global Handler cho Unobserved Task Exceptions
// App startup (Program.cs, App.xaml.cs)
TaskScheduler.UnobservedTaskException += (sender, args) =>
{
args.SetObserved(); // Ngăn crash process
Log.Error(args.Exception, "Unobserved task exception");
};
Best Practice
- Tránh async void trừ event handler.
- Luôn trả về
TaskhoặcTask<T>. - Trong event handler: try/catch nội bộ, log, UI feedback.
- Đăng ký
TaskScheduler.UnobservedTaskExceptionlàm safety net.