ThreadAbort yang diharapkan untuk Thread Latar Belakang

Saya punya yang berikut ini.

public static Thread testThread = new Thread(ThreadStart) {Name = "TestThread", IsBackground = true};
private void Form_Load()
{
    testThread.Start()
}
private static void ThreadStart()
{
    int count = 0;
    try
    {
        while (true)
        {
            count++;
        }
    }
    catch (Exception ex)
    {

        StreamWriter stream = new StreamWriter(File.OpenWrite("Exception.txt"));
        stream.WriteLine(count + "\n" + ex);
        stream.Flush();
        stream.Close();
    }
}

Ketika saya menelepon Thread.Abort() saya menangkap pengecualian dan menulis ke file. Namun, jika saya malah menutup aplikasinya, tidak ada yang tertulis. saya juga punya

AppDomain.CurrentDomain.UnhandledException +=
   new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);
Application.ThreadException +=
   new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);

Tapi sepertinya tidak ada pengecualian yang pernah diberikan.

Saya kira menambahkan pertanyaan adalah tindakan yang bijaksana.

Apa yang terjadi pada thread latar belakang yang berjalan ketika proses induk keluar? Pemahaman saya adalah ThreadAbortException dilemparkan untuk keluar dari thread. Jika hal ini terjadi, bagaimana ThreadAbortException dapat ditangkap untuk membersihkan sumber daya yang mungkin ada di thread?


person galford13x    schedule 05.02.2012    source sumber
comment
Bagaimana cara memulai threadnya? Mengapa Anda mengharapkan ThreadAbort dilempar? Dan apa pertanyaannya?   -  person Chris Shain    schedule 06.02.2012
comment
Dari semua bacaan saya, ketika aplikasi keluar, semua thread latar belakang yang berjalan dibatalkan melalui ThreadAbortException. Saya memulai thread menggunakan Thread.Start(ThreadStart)   -  person galford13x    schedule 06.02.2012
comment
@Chris: Di sinilah saya menerima beberapa informasi saya. stackoverflow.com/questions/1354196/   -  person galford13x    schedule 06.02.2012
comment
Mengapa Anda menggunakan Thread.Abort(). Membunuh benang itu buruk, oke? Lebih baik yakinkan mereka untuk bunuh diri, agar tidak masuk penjara.   -  person CodesInChaos    schedule 06.02.2012
comment
@CodeInChaos: Ini adalah latihan pendidikan. Namun pertanyaannya bagi Anda adalah, apakah Anda akan mempertimbangkan untuk menjadikan utas sebagai utas Latar Belakang lalu keluar dari penghentian aplikasi? Saya telah melihat ini dilakukan di banyak contoh dan perpustakaan dan selalu bertanya-tanya mengapa mereka tidak menggunakan pola yang berbeda untuk menyelesaikan pengakhiran thread dengan lebih baik. Itu sebabnya saya mengajukan pertanyaan itu sekarang.   -  person galford13x    schedule 06.02.2012


Jawaban (3)


Pertama-tama, aplikasi tersebut mungkin tidak keluar, karena Anda tidak menjadikannya sebagai thread latar belakang. Dugaan saya adalah Task Manager akan menampilkan salinan EXE Anda yang berjalan secara tidak terduga. Anda perlu menyetel Thread.IsBackground ke true pada objek thread sebelum memanggil Mulai.

Kedua, perilaku yang Anda harapkan secara eksplisit dibantah oleh dokumentasi:

Catatan

Saat runtime bahasa umum (CLR) menghentikan thread latar belakang, setelah semua thread latar depan dalam executable terkelola berakhir, thread tersebut tidak menggunakan System.Threading.Thread.Abort. Oleh karena itu, Anda tidak dapat menggunakan ThreadAbortException untuk mendeteksi kapan thread latar belakang dihentikan oleh CLR.

Sunting:

Saat suatu proses keluar, tidak perlu membersihkan sumber daya yang disimpan oleh thread pekerja karena, Anda tahu, proses sedang keluar. Kontrak yang berkaitan dengan thread latar belakang adalah bahwa thread tersebut dapat dimatikan kapan saja saat proses keluar. Oleh karena itu, jika thread latar belakang Anda melakukan sesuatu yang memerlukan kebenaran transaksional, thread tersebut mungkin bukan thread latar belakang. Buatlah thread latar depan dan mintalah secara berkala memeriksa atau menunggu peristiwa penyetelan ulang untuk melihat apakah thread tersebut harus keluar dan membiarkan proses berakhir.

person Chris Shain    schedule 05.02.2012
comment
Mengapa ini bukan thread latar belakang. Saya menyetel properti IsBackground = true ketika saya menginisialisasi utas. Saya akan memeriksa ulang apakah ini benar sekarang. - person galford13x; 06.02.2012
comment
Saya telah memeriksa ulang saat melakukan debug dan IsBackground untuk testThread ternyata benar. - person galford13x; 06.02.2012
comment
Dalam hal ini, lihat dokumentasi yang saya sebutkan di atas. MSDN memenangkan pendapat beberapa orang tentang stack overflow 99999 kali dari 100000. - person Chris Shain; 06.02.2012
comment
Tujuan saya adalah untuk tujuan pendidikan dalam memahami perbedaan antara thread latar belakang dan latar depan. Saya telah menggunakan perpustakaan di masa lalu yang mengandalkan thread latar belakang untuk keluar melalui keluar aplikasi. Mengenai sumber daya yang dilepaskan ketika aplikasi keluar, hal ini tidak sepenuhnya benar. Saya memiliki aplikasi yang telah membuka file tetapi keluar sebelum waktunya dan menahan kunci file meskipun tidak ada proses yang terdaftar di TaskManager. Satu-satunya cara untuk melepaskan kunci adalah dengan menggunakan alat khusus atau me-reboot sistem. - person galford13x; 06.02.2012
comment
AFAIK itu tidak mungkin dilakukan di Windows. Bisa jadi salah. Tentu saja tidak mungkin menggunakan konstruksi .NET I/O. Satu-satunya hal yang istimewa tentang thread latar belakang di .NET adalah bahwa thread tersebut tidak akan membuat prosesnya tetap berjalan. - person Chris Shain; 06.02.2012
comment
Poin bagusnya saya salah memahami beberapa postingan di stackoeverflow sebelumnya karena ada juga kutipan dari MSDN. Setelah membaca ulang, saya menyadari bahwa sebenarnya tidak ada pengecualian yang dilemparkan untuk menghentikan thread, hanya saja thread tersebut dihentikan. Tidak disebutkan bagaimana hal ini dilakukan. - person galford13x; 06.02.2012
comment
Saya memiliki program yang mengunci file di windows bahkan setelah file itu keluar. Meskipun saya mungkin tidak melihat proses yang tercantum di taskmanager, mungkin ada beberapa proses nakal/anak yang dimulai dan saya tidak tahu apa yang harus dicari. menggunakan sesuatu seperti technet.microsoft.com/en-us/sysinternals/bb896653.aspx, dapat memungkinkan Anda menemukan pelakunya dan membebaskan sumber daya. - person galford13x; 06.02.2012
comment
Referensi Anda ke dokumentasi MSDN paling dekat dengan apa yang saya cari, namun saya ingin tahu bagaimana CLR menyelesaikan pematian. Mengetahui bahwa saya tidak dapat mendeteksi penutupan latar belakang cukup berguna. Terima kasih atas bantuan Anda. - person galford13x; 06.02.2012
comment
Mungkin ingin membaca artikel tentang hosting CLR ini: msdn.microsoft. com/en-us/magazine/cc163567.aspx#S3. Ini tidak terlalu detail, tetapi akan mengarahkan Anda ke arah yang benar. - person Chris Shain; 06.02.2012
comment
Terima kasih Chris, saya akan memeriksanya. - person galford13x; 06.02.2012

Ketika CLR mematikan suatu proses, ia tidak memanggil Thread.Abort atau yang serupa. Metode thread Anda tidak akan keluar seperti metode utama Anda.

  1. Hal pertama yang dilakukannya ketika Anda keluar dari metode utama atau memanggil Environment.Exit adalah menyelesaikan semua objek dengan batas waktu (waktunya 2 detik di .NET 2.0) kemudian ia akan terus menghentikan aplikasi terlepas dari finalisator yang tertunda saat ini.
  2. Selanjutnya Finalis Kritis dipanggil.
  3. Kemudian semua thread ditangguhkan sehingga tidak menimbulkan bahaya saat CLR dimatikan.
  4. Aplikasi Anda telah keluar.
person Alois Kraus    schedule 05.02.2012

Jika properti IsBackground thread Anda adalah false , maka thread Anda akan tetap hidup, bahkan ketika jendela utama aplikasi Anda ditutup.

Cara terbaik untuk mengontrol masa pakai thread latar belakang adalah dengan membuat sentinel, yang biasanya diimplementasikan sebagai kolom volatile bool, yang diperiksa oleh kode dalam thread secara berkala (misalnya, pada setiap iterasi). Thread harus berhenti dijalankan ketika sentinel menunjukkan bahwa aplikasi dihentikan.

Kode berikut menunjukkan penggunaan sentinel untuk menghentikan thread setelah 200 milidetik:

public static Thread testThread = new Thread(ThreadStart) 
{
    Name = "TestThread", 
    IsBackground = false    // Allow thread to terminate naturally
};

private static volatile bool isTerminating = false;   // Sentinel

private void Form_Load()
{
    testThread.Start();
    Thread.Sleep(200);      // Sleep 200 milliseconds
    isTerminating = true;   // Set sentinel to terminate thread
}

private static void ThreadStart()
{
    int count = 0;

    while (!isTerminating)   // Keep looping until sentinel is set
        count++;

    using (StreamWriter stream = new StreamWriter(File.OpenWrite("Result.txt")))
    {
        stream.WriteLine(count);
        stream.Flush();
    }
}

Sunting: Untuk menjawab pertanyaan terakhir Anda, “Bagaimana ThreadAbortException bisa ditangkap untuk membersihkan sumber daya yang mungkin ada di thread?” Anda dapat menggunakan blok catch biasa. ThreadAbortException dapat ditangkap seperti pengecualian lainnya, tetapi secara otomatis akan dimunculkan kembali di akhir blok tangkapan. Namun, seperti yang disebutkan Chris, jika proses keluar, ThreadAbortException tidak dimunculkan sama sekali.

person Douglas    schedule 05.02.2012
comment
Seperti yang ditunjukkan, ini disetel ke true. Perhatikan bahwa new Thread(ThreadStart) {isBackground = true}; Namun saya akan memeriksa ulang untuk melihat apakah sebelum memulai thread itu benar. - person galford13x; 06.02.2012
comment
Saya memahami pola eksekusi Thread secara umum. Tapi ini untuk tujuan yang lebih mendidik dalam memahami apa yang terjadi ketika thread latar belakang keluar. Saya telah menggunakan perpustakaan yang daripada menggunakan pola Thread yang baik, mereka mengandalkan thread IsBackground untuk keluar dari thread. - person galford13x; 06.02.2012