Jika Anda memiliki banyak tugas logis yang membutuhkan pemrosesan konstan dan Anda ingin itu dilakukan secara paralel, gunakan pool + scheduler.
Jika Anda perlu membuat tugas terkait IO Anda secara bersamaan seperti mengunduh hal-hal dari server jarak jauh atau akses disk, tetapi perlu melakukan ini katakan sekali setiap beberapa menit, kemudian buat utas Anda sendiri dan bunuh mereka setelah Anda selesai.
Sunting: Tentang beberapa pertimbangan, saya menggunakan kumpulan utas untuk akses basis data, fisika / simulasi, AI (permainan), dan untuk tugas skrip yang dijalankan pada mesin virtual yang memproses banyak tugas yang ditentukan pengguna.
Biasanya kumpulan terdiri dari 2 utas per prosesor (jadi kemungkinan 4 saat ini), namun Anda dapat mengatur jumlah utas yang Anda inginkan, jika Anda tahu berapa banyak yang Anda butuhkan.
Sunting: Alasan untuk membuat utas Anda sendiri adalah karena perubahan konteks, (saat itulah utas perlu bertukar masuk dan keluar dari proses, bersama dengan ingatan mereka). Memiliki perubahan konteks yang tidak berguna, katakanlah ketika Anda tidak menggunakan utas Anda, hanya membiarkannya diam seperti yang dikatakan orang, dapat dengan mudah setengah kinerja program Anda (katakanlah Anda memiliki 3 utas tidur dan 2 utas aktif). Jadi jika mereka yang mengunduh utas hanya menunggu mereka menghabiskan banyak CPU dan mendinginkan cache untuk aplikasi Anda yang sebenarnya
Saya sarankan Anda menggunakan kumpulan utas di C # untuk alasan yang sama seperti bahasa lainnya.
Saat Anda ingin membatasi jumlah utas yang berjalan atau tidak ingin overhead membuat dan menghancurkannya, gunakan kumpulan utas.
Dengan tugas-tugas kecil, buku yang Anda baca berarti tugas-tugas dengan umur pendek. Jika diperlukan sepuluh detik untuk membuat utas yang hanya berjalan selama satu detik, itu adalah satu tempat di mana Anda harus menggunakan kumpulan (abaikan angka saya yang sebenarnya, itu adalah rasio yang diperhitungkan).
Kalau tidak, Anda menghabiskan sebagian besar waktu Anda untuk membuat dan menghancurkan utas daripada hanya melakukan pekerjaan yang seharusnya.
sumber
Berikut ini ringkasan bagus dari kumpulan utas di .Net: http://blogs.msdn.com/pedram/archive/2007/08/05/dedicated-thread-or-a-threadpool-thread.aspx
Posting juga memiliki beberapa poin tentang kapan Anda sebaiknya tidak menggunakan kumpulan utas dan memulai utas sendiri.
sumber
Saya sangat merekomendasikan membaca e-book gratis ini: Threading dalam C # oleh Joseph Albahari
Setidaknya baca bagian "Memulai". E-book menyediakan pengantar yang bagus dan menyertakan banyak informasi threading canggih juga.
Mengetahui apakah akan menggunakan kolam utas hanyalah awal. Selanjutnya Anda perlu menentukan metode memasuki kumpulan benang yang paling sesuai dengan kebutuhan Anda:
E-book ini menjelaskan semua ini dan menyarankan kapan menggunakannya vs membuat utas Anda sendiri.
sumber
Kumpulan utas dirancang untuk mengurangi pengalihan konteks di antara utas Anda. Pertimbangkan proses yang menjalankan beberapa komponen. Masing-masing komponen tersebut dapat membuat utas pekerja. Semakin banyak utas dalam proses Anda, semakin banyak waktu terbuang untuk pengalihan konteks.
Sekarang, jika masing-masing komponen mengantri item ke kumpulan thread, Anda akan memiliki konteks yang jauh lebih sedikit beralih overhead.
Thread pool dirancang untuk memaksimalkan pekerjaan yang dilakukan di seluruh CPU Anda (atau inti CPU). Itulah sebabnya, secara default, kumpulan utas memutar beberapa utas per prosesor.
Ada beberapa situasi di mana Anda tidak ingin menggunakan kolam utas. Jika Anda menunggu di I / O, atau menunggu di sebuah acara, dll maka Anda mengikat thread pool thread dan itu tidak dapat digunakan oleh orang lain. Gagasan yang sama berlaku untuk tugas yang berjalan lama, meskipun apa yang merupakan tugas jangka panjang itu subjektif.
Pax Diablo membuat poin yang bagus juga. Memutar utas tidak gratis. Butuh waktu dan mereka menggunakan memori tambahan untuk ruang stack mereka. Kumpulan utas akan menggunakan kembali utas untuk mengamortisasi biaya ini.
Catatan: Anda bertanya tentang menggunakan utas kumpulan utas untuk mengunduh data atau melakukan disk I / O. Anda tidak boleh menggunakan utas utas untuk ini (karena alasan yang saya uraikan di atas). Alih-alih menggunakan asynchronous I / O (alias metode BeginXX dan EndXX). Untuk
FileStream
itu akan menjadiBeginRead
danEndRead
. UntukHttpWebRequest
itu akan menjadiBeginGetResponse
danEndGetResponse
. Mereka lebih rumit untuk digunakan, tetapi mereka adalah cara yang tepat untuk melakukan I / O multi-threaded.sumber
Waspadai kumpulan .NET thread untuk operasi yang dapat memblokir bagian penting, variabel atau tidak dikenal dari pemrosesan mereka, karena rentan terhadap kelaparan thread. Pertimbangkan untuk menggunakan ekstensi paralel .NET, yang menyediakan sejumlah abstraksi logis atas operasi berulir. Mereka juga menyertakan penjadwal baru, yang seharusnya merupakan peningkatan pada ThreadPool. Lihat di sini
sumber
Salah satu alasan untuk menggunakan kumpulan utas hanya untuk tugas-tugas kecil adalah bahwa ada sejumlah utas utas yang terbatas. Jika seseorang digunakan untuk waktu yang lama maka itu menghentikan utas dari digunakan oleh kode lain. Jika ini terjadi berkali-kali maka pool thread dapat digunakan.
Menggunakan kumpulan thread dapat memiliki efek halus - beberapa .NET timer menggunakan utas thread thread dan tidak akan menyala, misalnya.
sumber
Jika Anda memiliki tugas latar belakang yang akan hidup untuk waktu yang lama, seperti untuk seumur hidup aplikasi Anda, maka membuat utas sendiri adalah hal yang wajar. Jika Anda memiliki pekerjaan pendek yang perlu dilakukan di utas, maka gunakan penggabungan ulir.
Dalam aplikasi tempat Anda membuat banyak utas, biaya overhead pembuatan utas menjadi substansial. Menggunakan kumpulan utas membuat utas sekali dan menggunakannya kembali, sehingga menghindari overhead pembuatan utas.
Dalam aplikasi yang saya kerjakan, mengubah dari membuat utas menjadi menggunakan kumpulan utas untuk utas yang berumur pendek benar-benar membantu put put aplikasi.
sumber
Untuk kinerja tertinggi dengan unit pelaksana bersamaan, tulis kumpulan utas Anda sendiri, tempat kumpulan objek Thread dibuat saat start up dan buka pemblokiran (sebelumnya ditangguhkan), menunggu konteks untuk dijalankan (objek dengan antarmuka standar yang diterapkan oleh kode Anda).
Begitu banyak artikel tentang Tugas vs. Utas vs. .NET ThreadPool gagal memberi Anda apa yang Anda butuhkan untuk membuat keputusan untuk kinerja. Tetapi ketika Anda membandingkannya, Thread menang dan terutama sekelompok Thread. Mereka didistribusikan terbaik di seluruh CPU dan mereka memulai lebih cepat.
Apa yang harus didiskusikan adalah fakta bahwa unit eksekusi utama Windows (termasuk Windows 10) adalah utas, dan konteks OS yang mengganti overhead biasanya dapat diabaikan. Sederhananya, saya belum dapat menemukan bukti yang meyakinkan dari banyak artikel ini, apakah artikel tersebut mengklaim kinerja yang lebih tinggi dengan menghemat pengalihan konteks atau penggunaan CPU yang lebih baik.
Sekarang untuk sedikit realisme:
Sebagian besar dari kita tidak akan membutuhkan aplikasi kita untuk menjadi deterministik, dan kebanyakan dari kita tidak memiliki latar belakang yang sulit dengan benang, yang misalnya sering disertai dengan pengembangan sistem operasi. Apa yang saya tulis di atas bukan untuk pemula.
Jadi yang mungkin paling penting untuk didiskusikan adalah apa yang mudah diprogram.
Jika Anda membuat kumpulan utas sendiri, Anda akan memiliki sedikit penulisan yang harus dilakukan karena Anda harus khawatir dengan melacak status eksekusi, cara mensimulasikan penangguhan dan melanjutkan, dan bagaimana membatalkan eksekusi - termasuk dalam aplikasi-lebar mematikan. Anda mungkin juga harus khawatir dengan apakah Anda ingin secara dinamis menumbuhkan kolam Anda dan juga batasan kapasitas apa yang akan dimiliki kolam Anda. Saya dapat menulis kerangka kerja seperti itu dalam satu jam, tetapi itu karena saya telah melakukannya berkali-kali.
Mungkin cara termudah untuk menulis unit eksekusi adalah dengan menggunakan Tugas. Keindahan dari sebuah Tugas adalah bahwa Anda dapat membuat satu dan menendang itu di-line dalam kode Anda (meskipun hati-hati mungkin diperlukan). Anda dapat memberikan token pembatalan untuk ditangani saat Anda ingin membatalkan Tugas. Selain itu, ia menggunakan pendekatan janji untuk merantai acara, dan Anda dapat membuatnya mengembalikan jenis nilai tertentu. Selain itu, dengan async dan menunggu, lebih banyak opsi ada dan kode Anda akan lebih portabel.
Pada dasarnya, penting untuk memahami pro dan kontra dengan Tugas vs Threads vs .NET ThreadPool. Jika saya membutuhkan kinerja tinggi, saya akan menggunakan utas, dan saya lebih suka menggunakan kolam saya sendiri.
Cara mudah untuk membandingkan adalah memulai utas 512 Thread, 512 Tugas, dan utas 512 ThreadPool. Anda akan menemukan penundaan di awal dengan Utas (karenanya, mengapa menulis kumpulan utas), tetapi semua Utas 512 akan berjalan dalam beberapa detik sementara Tugas dan. Utas ThreadPool NET membutuhkan waktu hingga beberapa menit untuk memulai.
Di bawah ini adalah hasil dari tes semacam itu (i5 quad core dengan 16 GB RAM), memberikan setiap 30 detik untuk berjalan. Kode yang dieksekusi menjalankan file I / O sederhana pada drive SSD.
Hasil tes
sumber
Kolam utas sangat bagus ketika Anda memiliki lebih banyak tugas untuk diproses daripada utas yang tersedia.
Anda dapat menambahkan semua tugas ke kumpulan utas dan menentukan jumlah utas maksimum yang dapat dijalankan pada waktu tertentu.
Lihat halaman ini di MSDN: http://msdn.microsoft.com/en-us/library/3dasc8as(VS.80).aspx
sumber
Selalu gunakan kumpulan utas jika memungkinkan, bekerjalah pada tingkat abstraksi setinggi mungkin. Kolam utas menyembunyikan menciptakan dan menghancurkan utas untuk Anda, ini biasanya hal yang baik!
sumber
Sebagian besar waktu Anda dapat menggunakan kolam karena Anda menghindari proses pembuatan utas yang mahal.
Namun dalam beberapa skenario Anda mungkin ingin membuat utas. Misalnya jika Anda bukan satu-satunya yang menggunakan kumpulan utas dan utas yang Anda buat berumur panjang (untuk menghindari konsumsi sumber daya bersama) atau misalnya jika Anda ingin mengontrol tumpukan ukuran utas.
sumber
Jangan lupa untuk menyelidiki pekerja Latar Belakang.
Saya menemukan banyak situasi, itu memberi saya apa yang saya inginkan tanpa beban berat.
Bersulang.
sumber
Saya biasanya menggunakan Threadpool setiap kali saya hanya perlu melakukan sesuatu pada utas lainnya dan tidak terlalu peduli ketika itu berjalan atau berakhir. Sesuatu seperti mencatat atau bahkan mengunduh latar belakang suatu file (walaupun ada cara yang lebih baik untuk melakukannya dengan gaya async). Saya menggunakan utas saya sendiri ketika saya membutuhkan lebih banyak kontrol. Juga apa yang saya temukan adalah menggunakan antrian Threadsafe (hack Anda sendiri) untuk menyimpan "perintah objek" bagus ketika saya memiliki beberapa perintah yang perlu saya kerjakan di> 1 utas. Jadi, Anda dapat membagi file Xml dan menempatkan setiap elemen dalam antrian dan kemudian memiliki beberapa utas yang berfungsi melakukan beberapa pemrosesan pada elemen-elemen ini. Saya menulis antrian seperti itu kembali di uni (VB.net!) Yang saya konversi menjadi C #. Saya memasukkannya di bawah ini tanpa alasan tertentu (kode ini mungkin mengandung beberapa kesalahan).
sumber
Saya ingin kumpulan utas untuk mendistribusikan pekerjaan lintas core dengan latensi sesedikit mungkin, dan itu tidak harus bekerja dengan baik dengan aplikasi lain. Saya menemukan bahwa kinerja .NET thread pool tidak sebaik yang seharusnya. Saya tahu saya ingin satu utas per inti, jadi saya menulis kelas pengganti kumpulan utas saya sendiri. Kode ini diberikan sebagai jawaban untuk pertanyaan StackOverflow lain di sini .
Mengenai pertanyaan awal, kumpulan thread berguna untuk memecah komputasi berulang menjadi bagian-bagian yang dapat dieksekusi secara paralel (dengan asumsi mereka dapat dieksekusi secara paralel tanpa mengubah hasilnya). Manajemen utas manual berguna untuk tugas-tugas seperti UI dan IO.
sumber