Saya memiliki beberapa masalah dengan jawaban utama untuk pertanyaan ini.
Pertama, dalam situasi api-dan-lupakan yang sebenarnya , Anda mungkin tidak akan await
melakukan tugas itu, jadi tidak ada gunanya menambahkan ConfigureAwait(false)
. Jika Anda tidak await
mengembalikan nilai ConfigureAwait
, maka itu tidak mungkin berpengaruh.
Kedua, Anda perlu menyadari apa yang terjadi saat tugas selesai dengan pengecualian. Pertimbangkan solusi sederhana yang disarankan @ ade-miller:
Task.Factory.StartNew(SomeMethod); // .NET 4.0
Task.Run(SomeMethod); // .NET 4.5
Ini menimbulkan bahaya: jika pengecualian yang tidak tertangani lolos dari SomeMethod()
, pengecualian itu tidak akan pernah diamati, dan mungkin 1 dicabut kembali pada utas finalizer, membuat aplikasi Anda mogok. Oleh karena itu, saya akan merekomendasikan menggunakan metode helper untuk memastikan bahwa pengecualian yang dihasilkan diamati.
Anda bisa menulis sesuatu seperti ini:
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);
}
}
}
Implementasi ini harus memiliki overhead minimal: kelanjutan hanya dipanggil jika tugas tidak berhasil diselesaikan, dan harus dijalankan secara sinkron (bukan dijadwalkan secara terpisah dari tugas asli). Dalam kasus "malas", Anda bahkan tidak akan dikenai alokasi untuk delegasi kelanjutan.
Memulai operasi asinkron kemudian menjadi sepele:
Blindly.Run(SomeMethod); // Ignore error
Blindly.Run(SomeMethod, e => Log.Warn("Whoops", e)); // Log error
1. Ini adalah perilaku default di .NET 4.0. Dalam .NET 4.5, perilaku default diubah sedemikian rupa sehingga pengecualian yang tidak teramati tidak akan ditampilkan kembali pada utas finalizer (meskipun Anda masih dapat mengamati mereka melalui acara UnobservedTaskException di TaskScheduler). Namun, konfigurasi default dapat diganti, dan meskipun aplikasi Anda memerlukan .NET 4.5, Anda tidak boleh berasumsi bahwa pengecualian tugas yang tidak teramati tidak akan berbahaya.