Saya punya pertanyaan gaya tentang pilihan implementasi latar belakang thread yang harus saya gunakan pada aplikasi windows form. Saat ini saya memiliki BackgroundWorker
formulir yang memiliki infinite (while(true))
loop. Dalam loop ini saya gunakan WaitHandle.WaitAny
untuk menjaga agar thread tetap tertunda sampai sesuatu yang menarik terjadi. Salah satu pegangan acara yang saya tunggu adalah acara " StopThread
" sehingga saya bisa keluar dari loop. Peristiwa ini ditandai ketika saya ditimpa Form.Dispose()
.
Saya membaca suatu tempat yang BackgroundWorker
benar-benar ditujukan untuk operasi yang Anda tidak ingin mengikat UI dengan dan memiliki akhir yang terbatas - seperti mengunduh file, atau memproses urutan item. Dalam hal ini "akhir" tidak diketahui dan hanya ketika jendela ditutup. Oleh karena itu apakah lebih tepat bagi saya untuk menggunakan Thread latar belakang daripada BackgroundWorker
untuk tujuan ini?
sumber
CancelAsync
(dan ujiCancellationPending
apakah thread Anda akan polling pada interval pendek, jika Anda ingin memiliki pengecualian yang diangkat, gunakanSystem.Threading.Thread.Abort()
yang meningkatkan pengecualian di dalam blok thread itu sendiri, pilih model yang tepat untuk situasi ini.Beberapa pemikiran saya ...
sumber
BackgroundWorker
dirancang untuk melaporkan kemajuan utas ke pihak yang berkepentingan, yang biasanya melibatkan UI. Dokumentasi MSDN untuk kelas membuatnya sangat jelas. Jika Anda hanya perlu melakukan tugas di latar belakang, lebih baik menggunakanThreadPool
utas.System.Windows.Forms
majelis;BackgroundWorker
juga berguna untuk aplikasi WPF dan aplikasi tersebut mungkin tidak memiliki referensi ke WinForms.Cukup banyak apa yang dikatakan Matt Davis, dengan poin tambahan berikut:
Bagi saya pembeda utama dengan
BackgroundWorker
adalah marshalling otomatis dari acara selesai melaluiSynchronizationContext
. Dalam konteks UI, ini berarti acara yang selesai diaktifkan pada utas UI, dan karenanya dapat digunakan untuk memperbarui UI. Ini adalah pembeda utama jika Anda menggunakanBackgroundWorker
dalam konteks UI.Tugas yang dieksekusi melalui the
ThreadPool
tidak dapat dengan mudah dibatalkan (ini termasukThreadPool
.QueueUserWorkItem
Dan delegasi mengeksekusi secara asinkron). Jadi sementara itu menghindari overhead dari perputaran thread, jika Anda perlu pembatalan baik menggunakanBackgroundWorker
atau (lebih mungkin di luar UI) putar sebuah thread dan simpan referensi untuk itu sehingga Anda dapat meneleponAbort()
.sumber
Anda juga mengikat utas threadpool untuk seumur hidup pekerja latar belakang, yang mungkin menjadi perhatian karena hanya ada sejumlah terbatas dari mereka. Saya akan mengatakan bahwa jika Anda hanya pernah membuat utas sekali untuk aplikasi Anda (dan tidak menggunakan salah satu fitur pekerja latar belakang) maka gunakan utas, bukan utas pengrajin latar / threadpool.
sumber
Anda tahu, kadang-kadang lebih mudah untuk bekerja dengan BackgroundWorker terlepas dari apakah Anda menggunakan Windows Forms, WPF atau teknologi apa pun. Bagian yang rapi tentang orang-orang ini adalah Anda mendapatkan threading tanpa harus terlalu khawatir tentang di mana Anda menjalankan thread, yang bagus untuk tugas-tugas sederhana.
Sebelum menggunakan
BackgroundWorker
pertimbangan terlebih dahulu jika Anda ingin membatalkan utas (aplikasi penutupan, pembatalan pengguna) maka Anda harus memutuskan apakah utas Anda harus memeriksa pembatalan atau apakah harus diarahkan pada eksekusi itu sendiri.BackgroundWorker.CancelAsync()
akan diaturCancellationPending
ketrue
tetapi tidak akan melakukan apa-apa lagi, tanggung jawab utas untuk terus memeriksa ini, perlu diingat juga bahwa Anda bisa berakhir dengan kondisi balapan dalam pendekatan ini di mana pengguna Anda dibatalkan, tetapi utas selesai sebelum pengujian untukCancellationPending
.Thread.Abort()
di sisi lain akan melempar pengecualian dalam eksekusi utas yang memberlakukan pembatalan utas itu, Anda harus berhati-hati tentang apa yang mungkin berbahaya jika pengecualian ini tiba-tiba muncul dalam eksekusi sekalipun.Threading perlu pertimbangan yang sangat hati-hati apa pun tugasnya, untuk bacaan lebih lanjut:
Pemrograman Paralel dalam .NET Framework Managed Threading Best Practices
sumber
Saya tahu cara menggunakan utas sebelum saya tahu. NET, jadi butuh waktu untuk membiasakan diri ketika saya mulai menggunakan
BackgroundWorker
s. Matt Davis telah merangkum perbedaannya dengan keunggulan luar biasa, tetapi saya ingin menambahkan bahwa lebih sulit untuk memahami dengan tepat apa yang dilakukan oleh kode, dan ini dapat membuat proses debug lebih sulit. Lebih mudah untuk berpikir tentang membuat dan mematikan utas, IMO, daripada memikirkan memberi pekerjaan pada kumpulan utas.Saya masih belum bisa mengomentari pos orang lain, jadi maafkan ketimpangan sesaat saya dalam menggunakan jawaban untuk mengatasi piers7
Jangan gunakan
Thread.Abort();
, beri tanda suatu acara dan rancang utas Anda untuk berakhir dengan anggun saat diisyaratkan.Thread.Abort()
memunculkanThreadAbortException
pada titik sewenang-wenang dalam eksekusi utas, yang dapat melakukan semua jenis hal-hal yang tidak bahagia seperti Monitor yatim, negara bersama yang korup, dan sebagainya.http://msdn.microsoft.com/en-us/library/system.threading.thread.abort.aspx
sumber
Jika tidak rusak - perbaiki sampai ... hanya bercanda :)
Tapi serius BackgroundWorker mungkin sangat mirip dengan apa yang sudah Anda miliki, seandainya Anda memulainya dari awal mungkin Anda akan menghemat waktu - tetapi pada titik ini saya tidak melihat kebutuhan. Kecuali ada sesuatu yang tidak berfungsi, atau Anda pikir kode Anda saat ini sulit dimengerti, maka saya akan tetap dengan apa yang Anda miliki.
sumber
Perbedaan dasarnya adalah, seperti yang Anda nyatakan, menghasilkan peristiwa GUI dari
BackgroundWorker
. Jika utas tidak perlu memperbarui tampilan atau membuat acara untuk utas GUI utama, maka utas tersebut dapat sederhana.sumber
Saya ingin menunjukkan satu perilaku kelas BackgroundWorker yang belum disebutkan. Anda bisa membuat Thread normal untuk berjalan di latar belakang dengan mengatur properti Thread.IsBackground.
Anda bisa menguji perilaku ini dengan memanggil metode berikut di konstruktor jendela formulir Anda.
Ketika properti IsBackground disetel ke true dan Anda menutup jendela, maka aplikasi Anda akan berakhir secara normal.
Tetapi ketika properti IsBackground diatur ke false (secara default) dan Anda menutup jendela, maka hanya jendela yang akan menghilang tetapi prosesnya tetap berjalan.
Kelas BackgroundWorker memanfaatkan Thread yang berjalan di latar belakang.
sumber
Pekerja latar belakang adalah kelas yang bekerja di utas terpisah, tetapi menyediakan fungsionalitas tambahan yang tidak Anda dapatkan dengan Utas sederhana (seperti penanganan laporan progres tugas).
Jika Anda tidak memerlukan fitur tambahan yang diberikan oleh pekerja latar belakang - dan sepertinya Anda tidak - maka Thread akan lebih sesuai.
sumber
Yang membingungkan bagi saya adalah bahwa desainer studio visual hanya memungkinkan Anda untuk menggunakan BackgroundWorkers dan Timers yang tidak benar-benar bekerja dengan proyek layanan.
Ini memberi Anda kontrol seret dan lepas yang rapi ke layanan Anda, tetapi ... bahkan tidak mencoba menggunakannya. Tidak akan bekerja
Layanan: Hanya gunakan System.Timers.Timer System.Windows.Forms.Timer tidak akan berfungsi meskipun tersedia di kotak alat
Layanan: BackgroundWorkers tidak akan berfungsi saat berjalan sebagai layanan Gunakan System.Threading.ThreadPools sebagai gantinya atau panggilan Async
sumber