Saya tidak pernah benar-benar menggunakan threading sebelumnya di C # di mana saya perlu memiliki dua utas, serta utas UI utama. Pada dasarnya, saya memiliki yang berikut ini.
public void StartTheActions()
{
//Starting thread 1....
Thread t1 = new Thread(new ThreadStart(action1));
t1.Start();
// Now, I want for the main thread (which is calling `StartTheActions` method)
// to wait for `t1` to finish. I've created an event in `action1` for this.
// The I wish `t2` to start...
Thread t2 = new Thread(new ThreadStart(action2));
t2.Start();
}
Jadi, pada dasarnya, pertanyaan saya adalah bagaimana agar utas menunggu yang lain selesai. Apa cara terbaik untuk melakukan ini?
c#
multithreading
Maxim Zaslavsky
sumber
sumber
Jawaban:
Saya dapat melihat 5 opsi yang tersedia:
1. Utas. Gabung
Seperti jawaban Mitch. Tapi ini akan memblokir utas UI Anda, namun Anda mendapatkan Timeout bawaan untuk Anda.
2. Gunakan a
WaitHandle
ManualResetEvent
adalahWaitHandle
seperti yang disarankan jrista.Satu hal yang perlu diperhatikan adalah jika Anda ingin menunggu beberapa utas,
WaitHandle.WaitAll()
tidak akan berfungsi secara default, karena membutuhkan utas MTA. Anda dapat menyiasatinya dengan menandaiMain()
metode Anda denganMTAThread
- namun ini memblokir pompa pesan Anda dan tidak direkomendasikan dari apa yang saya baca.3. Menembak sebuah acara
Lihat halaman ini oleh Jon Skeet tentang acara dan multi-threading, ada kemungkinan bahwa suatu peristiwa dapat menjadi tidak bertuliskan antara
if
danEventName(this,EventArgs.Empty)
- itu terjadi pada saya sebelumnya.(Semoga kompilasi ini, saya belum mencoba)
4. Gunakan delegasi
Jika Anda menggunakan metode _count, mungkin ide (agar aman) untuk menambahkannya menggunakan
Interlocked.Increment(ref _count)
Saya tertarik untuk mengetahui perbedaan antara menggunakan delegasi dan acara untuk pemberitahuan utas, satu-satunya perbedaan yang saya tahu adalah acara disebut serempak.
5. Sebagai gantinya, lakukan secara asinkron
Jawaban atas pertanyaan ini memiliki deskripsi yang sangat jelas tentang opsi Anda dengan metode ini.
Delegasi / Acara di utas yang salah
Cara event / delegate melakukan sesuatu akan berarti metode event handler Anda ada di thread1 / thread2 bukan utas UI utama , jadi Anda harus beralih kembali tepat di atas metode HandleThreadDone:
sumber
Menambahkan
setelah Anda memulainya, tetapi itu tidak akan mencapai apa-apa karena pada dasarnya sama dengan menjalankan di utas utama!
Saya bisa sangat merekomendasikan membaca Joe Albahari's Threading di C # e-book gratis, jika Anda ingin mendapatkan pemahaman tentang threading di .NET.
sumber
Join
secara harfiah apa yang diminta oleh si penanya, ini bisa sangat buruk secara umum. Panggilan keJoin
akan menutup utas dari mana ini dilakukan. Jika itu adalah utas GUI utama, ini BURUK ! Sebagai pengguna, saya secara aktif membenci aplikasi yang sepertinya berfungsi seperti ini. Jadi, silakan lihat semua jawaban lain untuk pertanyaan ini dan stackoverflow.com/questions/1221374/...Dua jawaban sebelumnya sangat bagus, dan akan bekerja untuk skenario sederhana. Namun, ada beberapa cara lain untuk menyinkronkan utas. Berikut ini juga akan berfungsi:
ManualResetEvent adalah salah satu dari berbagai WaitHandle yang ditawarkan oleh .NET framework. Mereka dapat memberikan kemampuan sinkronisasi thread yang lebih kaya daripada alat yang sederhana namun sangat umum seperti lock () / Monitor, Thread.Join, dll. Mereka juga dapat digunakan untuk menyinkronkan lebih dari dua thread, memungkinkan skenario yang kompleks seperti thread 'master' yang mengoordinasikan banyak utas 'anak', beberapa proses bersamaan yang bergantung pada beberapa tahap satu sama lain untuk disinkronkan, dll.
sumber
Jika menggunakan dari .NET 4 sampel ini dapat membantu Anda:
dari: https://stackoverflow.com/a/4190969/1676736
sumber
Anda ingin
Thread.Join()
metode ini, atau salah satu kelebihannya .sumber
Saya ingin utas utama Anda meneruskan metode panggilan balik ke utas pertama Anda, dan setelah selesai, ia akan memanggil metode panggil balik pada mainthread, yang dapat meluncurkan utas kedua. Ini menjaga agar utas utama Anda tidak menggantung saat menunggu Gabung atau Waithandle. Melewati metode sebagai delegasi adalah hal yang berguna untuk dipelajari dengan C #.
sumber
Coba ini:
sumber
Posting ke mungkin membantu beberapa orang lain, menghabiskan sedikit waktu mencari solusi seperti apa yang saya hasilkan. Jadi saya mengambil pendekatan yang sedikit berbeda. Ada opsi penghitung di atas, saya hanya menerapkannya sedikit berbeda. Saya memutar banyak thread dan menambah counter dan mengurangi counter ketika thread mulai dan berhenti. Kemudian dalam metode utama saya ingin berhenti dan menunggu utas untuk menyelesaikan saya lakukan.
Didokumentasikan di blog saya. http://www.adamthings.com/post/2012/07/11/ensure-threads-have-finished-before-method-continues-in-c/
sumber
Ketika saya ingin UI dapat memperbarui tampilannya sambil menunggu tugas selesai, saya menggunakan loop sementara yang menguji IsAlive di utas:
sumber
Berikut adalah contoh sederhana yang menunggu tapak selesai, dalam kelas yang sama. Itu juga membuat panggilan ke kelas lain di namespace yang sama. Saya menyertakan pernyataan "using" sehingga dapat dieksekusi sebagai Winform selama Anda membuat tombol1.
sumber