Saya sangat suka pertanyaan ini:
Cara termudah untuk melakukan metode api dan lupa di C #?
Saya hanya ingin tahu bahwa sekarang kita memiliki ekstensi Paralel di C # 4.0, adakah cara yang lebih bersih untuk melakukan Fire & Forget dengan Parallel linq?
c#
.net
.net-4.0
task-parallel-library
fire-and-forget
Jonathon Kresner
sumber
sumber
Jawaban:
Bukan jawaban untuk 4.0, tetapi perlu dicatat bahwa di .Net 4.5 Anda dapat membuatnya lebih sederhana dengan:
Pragma adalah menonaktifkan peringatan yang memberi tahu Anda bahwa Anda menjalankan Tugas ini sebagai api dan lupa.
Jika metode di dalam kurung kurawal mengembalikan Tugas:
Mari kita uraikan:
Task.Run mengembalikan sebuah Tugas, yang menghasilkan peringatan kompilator (peringatan CS4014) yang mencatat bahwa kode ini akan dijalankan di latar belakang - itulah yang Anda inginkan, jadi kami menonaktifkan peringatan 4014.
Secara default, Tasks mencoba untuk "mengirim kembali ke Thread asli," yang berarti bahwa Tugas ini akan berjalan di latar belakang, kemudian mencoba untuk kembali ke Thread yang memulainya. Seringkali aktifkan dan lupakan Tugas selesai setelah Thread asli selesai. Itu akan menyebabkan ThreadAbortException dilempar. Dalam kebanyakan kasus, ini tidak berbahaya - hanya memberi tahu Anda, saya mencoba bergabung kembali, saya gagal, tetapi Anda toh tidak peduli. Tapi masih agak berisik untuk memiliki ThreadAbortExceptions baik di log Anda di Produksi, atau di debugger Anda di dev lokal.
.ConfigureAwait(false)
hanyalah cara untuk tetap rapi dan secara eksplisit mengatakan, menjalankan ini di latar belakang, dan hanya itu.Karena ini bertele-tele, terutama pragma jelek, saya menggunakan metode perpustakaan untuk ini:
Pemakaian:
sumber
ConfigureAwait(false)
padaTask.Run
saat Anda tidakawait
tugas. Tujuan dari fungsi ini ada dalam namanya: "konfigurasi await ". Jika Anda tidak melakukanawait
tugas tersebut, Anda tidak mendaftarkan kelanjutan, dan tidak ada kode untuk tugas "marshal kembali ke utas asli", seperti yang Anda katakan. Risiko yang lebih besar adalah pengecualian yang tidak teramati ditampilkan kembali pada utas finalizer, yang bahkan tidak ditangani oleh jawaban ini.#Disable Warning BC42358
Dengan
Task
kelas ya, tetapi PLINQ benar-benar untuk menanyakan koleksi.Sesuatu seperti berikut ini akan melakukannya dengan Tugas.
Atau bahkan...
Atau...
dimana
FireAway
adalahJadi berdasarkan ketegasan nama kelas dan metode ini mengalahkan versi threadpool dengan antara enam dan sembilan belas karakter tergantung pada yang Anda pilih :)
sumber
fire and forget in ASP.NET WebForms and windows.close()
?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 menambahkanConfigureAwait(false)
. Jika Anda tidakawait
mengembalikan nilaiConfigureAwait
, maka itu tidak mungkin berpengaruh.Kedua, Anda perlu menyadari apa yang terjadi saat tugas selesai dengan pengecualian. Pertimbangkan solusi sederhana yang disarankan @ ade-miller:
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:
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:
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.
sumber
ContinueWith
dipanggil karena pembatalan, properti pengecualian anteseden akan menjadi Null dan pengecualian referensi null akan dilemparkan. Menetapkan opsi kelanjutan tugas keOnlyOnFaulted
akan menghilangkan kebutuhan akan pemeriksaan nol atau memeriksa apakah pengecualiannya null sebelum menggunakannya.Task
menjadi detail implementasi.Task
" tidak sama dengan "Saya ingin cara sederhana untuk memulai operasi latar belakang, tidak pernah mengamati hasilnya, dan saya tidak peduli mekanisme apa yang digunakan untuk melakukannya. " Atas dasar itu, saya mendukung jawaban saya atas pertanyaan yang diajukan .fire and forget
di ASP.NET WebForms danwindows.close()
?Hanya untuk memperbaiki beberapa masalah yang akan terjadi dengan jawaban Mike Strobel:
Jika Anda menggunakan
var task = Task.Run(action)
dan setelah menetapkan kelanjutan untuk tugas itu, maka Anda akan menghadapi risikoTask
membuat beberapa pengecualian sebelum Anda menetapkan kelanjutan penangan pengecualian keTask
. Jadi, kelas di bawah ini harus bebas dari risiko ini:Di sini,
task
tidak dijalankan secara langsung, melainkan dibuat, kelanjutan ditetapkan, dan baru kemudian tugas dijalankan untuk menghilangkan risiko tugas menyelesaikan eksekusi (atau memunculkan beberapa pengecualian) sebelum menetapkan kelanjutan.The
Run
Metode sini kembali kelanjutanTask
sehingga saya bisa menulis unit test memastikan eksekusi selesai. Anda dapat dengan aman mengabaikannya dalam penggunaan Anda.sumber