Tôi có một vài vấn đề với câu trả lời hàng đầu cho câu hỏi này.
Đầu tiên, trong một tình huống cháy nổ thực sự , bạn có thể sẽ không thực await
hiện nhiệm vụ, vì vậy việc phụ thêm cũng vô ích ConfigureAwait(false)
. Nếu bạn không await
trả về giá trị ConfigureAwait
, thì nó không thể có bất kỳ tác dụng nào.
Thứ hai, bạn cần biết điều gì sẽ xảy ra khi nhiệm vụ hoàn thành với một ngoại lệ. Hãy xem xét giải pháp đơn giản mà @ ade-miller đã đề xuất:
Task.Factory.StartNew(SomeMethod); // .NET 4.0
Task.Run(SomeMethod); // .NET 4.5
Điều này dẫn đến một mối nguy hiểm: nếu một ngoại lệ chưa được xử lý thoát khỏi SomeMethod()
, ngoại lệ đó sẽ không bao giờ được quan sát và 1 có thể được phát triển lại trên chuỗi trình hoàn thiện, làm hỏng ứng dụng của bạn. Do đó, tôi khuyên bạn nên sử dụng phương pháp trợ giúp để đảm bảo rằng mọi ngoại lệ kết quả đều được tuân thủ.
Bạn có thể viết một cái gì đó như thế này:
public static class Blindly
{
private static readonly Action<Task> DefaultErrorContinuation =
t =>
{
try { t.Wait(); }
catch {}
};
public static void Run(Action action, Action<Exception> handler = null)
{
if (action == null)
throw new ArgumentNullException(nameof(action));
var task = Task.Run(action); // Adapt as necessary for .NET 4.0.
if (handler == null)
{
task.ContinueWith(
DefaultErrorContinuation,
TaskContinuationOptions.ExecuteSynchronously |
TaskContinuationOptions.OnlyOnFaulted);
}
else
{
task.ContinueWith(
t => handler(t.Exception.GetBaseException()),
TaskContinuationOptions.ExecuteSynchronously |
TaskContinuationOptions.OnlyOnFaulted);
}
}
}
Việc triển khai này phải có chi phí tối thiểu: phần tiếp tục chỉ được gọi nếu tác vụ không hoàn thành thành công và nó phải được gọi đồng bộ (trái ngược với việc được lên lịch riêng với tác vụ ban đầu). Trong trường hợp "lười biếng", bạn thậm chí sẽ không bị phân bổ cho đại biểu tiếp tục.
Bắt đầu một hoạt động không đồng bộ sau đó trở nên tầm thường:
Blindly.Run(SomeMethod); // Ignore error
Blindly.Run(SomeMethod, e => Log.Warn("Whoops", e)); // Log error
1. Đây là hành vi mặc định trong .NET 4.0. Trong .NET 4.5, hành vi mặc định đã được thay đổi để các ngoại lệ không được quan sát sẽ không được phát triển lại trên chuỗi trình hoàn thiện (mặc dù bạn vẫn có thể quan sát chúng qua sự kiện UnobservedTaskException trên TaskScheduler). Tuy nhiên, cấu hình mặc định có thể bị ghi đè và ngay cả khi ứng dụng của bạn yêu cầu .NET 4.5, bạn không nên cho rằng các ngoại lệ tác vụ không được quan sát sẽ vô hại.