menangkap pengecualian yang dilemparkan ke utas berbeda
110
Salah satu metode saya ( Method1) memunculkan utas baru. Utas itu mengeksekusi metode ( Method2) dan selama pelaksanaan pengecualian dilempar. Saya perlu mendapatkan informasi pengecualian itu pada metode pemanggilan ( Method1)
Apakah bagaimanapun saya bisa menangkap pengecualian ini Method1yang dilemparkan Method2?
Di .NET 4 dan yang lebih baru, Anda dapat menggunakan Task<T>kelas daripada membuat utas baru. Kemudian Anda bisa mendapatkan pengecualian menggunakan .Exceptionsproperti pada objek tugas Anda. Ada 2 cara untuk melakukannya:
Dalam metode terpisah: // Anda memproses pengecualian di thread beberapa tugas
Maaf, tetapi saya lupa menyebutkan bahwa saya menggunakan .NET 3.5. Sesuai pemahaman saya Task adalah 4.0 hal?
Silverlight Student
2
@SilverlightStudent Ok, saya baru saja memperbarui jawaban saya untuk memenuhi kebutuhan Anda.
oxilumin
@oxilumin: Terima kasih dan sangat dihargai. Satu pertanyaan lanjutan lagi. Jika metode Test () Anda juga membutuhkan beberapa argumen, lalu bagaimana Anda akan mengubah metode SafeExecute untuk argumen tersebut?
Silverlight Student
2
@SilverlightStudent Dalam hal ini saya akan memberikan lambda, bukan Test. Seperti() => Test(myParameter1, myParameter2)
oxilumin
2
@SilverlightStudent: Diperbarui.
oxilumin
9
Anda tidak dapat menangkap pengecualian di Metode1. Namun, Anda dapat menangkap pengecualian di Metode2 dan merekamnya ke variabel yang kemudian dapat dibaca dan dikerjakan oleh utas eksekusi asli.
Terimakasih atas tanggapan Anda. Jadi Jika Metode1 adalah bagian dari Kelas1 dan saya memiliki variabel tipe Pengecualian di kelas itu. Setiap kali Method2 melontarkan pengecualian, itu menetapkan variabel pengecualian itu di Kelas1 juga. Apakah ini terdengar seperti desain yang adil? Apakah ada cara praktik terbaik untuk menangani skenario ini?
Silverlight Student
Benar, Anda cukup menyimpan pengecualian dan mengaksesnya nanti. Tidak jarang metode yang dijalankan di masa mendatang (terutama callback ketika Method2 selesai) untuk kemudian menampilkan kembali pengecualian tersebut seolah-olah mereka sendirilah yang menyebabkannya, tetapi ini benar-benar tergantung pada apa yang Anda inginkan.
ermau
0
Metode paling sederhana untuk berbagi data di antara utas yang berbeda adalah shared datasebagai berikut (beberapa adalah kode pseudo):
classMyThread{publicstringSharedData;publicvoidWorker(){...lengthy action, infinite loop, etc...SharedData="whatever";...lengthy action...return;}}classProgram{staticvoidMain(){MyThread m =newMyThread();ThreadWorkerThread=newThread(m.Worker);WorkerThread.Start();
loop//or e.g. a Timer thread{
f(m.SharedData);}return;}}
Anda dapat membaca tentang metode ini dalam pengantar yang bagus tentang multithreading ini , namun, saya lebih suka membaca tentang ini di O'Reilly book C# 3.0 in a nutshell, oleh saudara-saudara Albahari (2007), yang juga dapat diakses secara bebas di Google Buku, seperti versi buku yang lebih baru, karena ini juga mencakup kumpulan thread, thread latar depan versus latar belakang, dll., dengan kode contoh yang bagus dan sederhana. (Penafian: Saya memiliki salinan buku ini yang sudah usang)
Jika Anda membuat aplikasi WinForms, penggunaan data bersama sangat berguna, karena kontrol WinForm tidak aman untuk thread. Menggunakan callback untuk meneruskan data dari thread pekerja kembali ke kontrol WinForm, thread UI utama memerlukan kode jelek Invoke()untuk membuat kontrol thread tersebut aman. Menggunakan data bersama sebagai gantinya, dan single-threaded System.Windows.Forms.Timer, dengan waktu singkat Intervalkatakanlah 0,2 detik, Anda dapat dengan mudah mengirim informasi dari thread pekerja ke kontrol tanpa Invoke.
Saya memiliki masalah khusus karena saya ingin menggunakan item, yang berisi kontrol, dari rangkaian pengujian integrasi, jadi harus membuat thread STA. Kode yang saya dapatkan adalah sebagai berikut, taruh di sini jika orang lain memiliki masalah yang sama.
publicBoolean?Dance(String name){// Already on an STA thread, so just go for itif(Thread.CurrentThread.GetApartmentState()==ApartmentState.STA)returnDanceSTA(name);// Local variable to hold the caught exception until the caller can rethrowException lException =null;Boolean? lResult =null;// A gate to hold the calling thread until the called thread is donevar lGate =newManualResetEvent(false);var lThreadStart =newThreadStart(()=>{try{
lResult =DanceSTA(name);}catch(Exception ex){
lException = ex;}
lGate.Set();});var lThread =newThread(lThreadStart);
lThread.SetApartmentState(ApartmentState.STA);
lThread.Start();
lGate.WaitOne();if(lException !=null)throw lException;return lResult;}publicBoolean?DanceSTA(String name){...}
Ini adalah tempel langsung dari kode apa adanya. Untuk kegunaan lain, saya akan merekomendasikan menyediakan tindakan atau fungsi sebagai parameter dan menjalankannya di utas alih-alih melakukan pengkodean keras metode yang disebut.
Test
. Seperti() => Test(myParameter1, myParameter2)
Anda tidak dapat menangkap pengecualian di Metode1. Namun, Anda dapat menangkap pengecualian di Metode2 dan merekamnya ke variabel yang kemudian dapat dibaca dan dikerjakan oleh utas eksekusi asli.
sumber
Metode paling sederhana untuk berbagi data di antara utas yang berbeda adalah
shared data
sebagai berikut (beberapa adalah kode pseudo):Anda dapat membaca tentang metode ini dalam pengantar yang bagus tentang multithreading ini , namun, saya lebih suka membaca tentang ini di
O'Reilly book C# 3.0 in a nutshell
, oleh saudara-saudara Albahari (2007), yang juga dapat diakses secara bebas di Google Buku, seperti versi buku yang lebih baru, karena ini juga mencakup kumpulan thread, thread latar depan versus latar belakang, dll., dengan kode contoh yang bagus dan sederhana. (Penafian: Saya memiliki salinan buku ini yang sudah usang)Jika Anda membuat aplikasi WinForms, penggunaan data bersama sangat berguna, karena kontrol WinForm tidak aman untuk thread. Menggunakan callback untuk meneruskan data dari thread pekerja kembali ke kontrol WinForm, thread UI utama memerlukan kode jelek
Invoke()
untuk membuat kontrol thread tersebut aman. Menggunakan data bersama sebagai gantinya, dan single-threadedSystem.Windows.Forms.Timer
, dengan waktu singkatInterval
katakanlah 0,2 detik, Anda dapat dengan mudah mengirim informasi dari thread pekerja ke kontrol tanpaInvoke
.sumber
Saya memiliki masalah khusus karena saya ingin menggunakan item, yang berisi kontrol, dari rangkaian pengujian integrasi, jadi harus membuat thread STA. Kode yang saya dapatkan adalah sebagai berikut, taruh di sini jika orang lain memiliki masalah yang sama.
Ini adalah tempel langsung dari kode apa adanya. Untuk kegunaan lain, saya akan merekomendasikan menyediakan tindakan atau fungsi sebagai parameter dan menjalankannya di utas alih-alih melakukan pengkodean keras metode yang disebut.
sumber