Saya mencari ide bagus untuk menerapkan cara umum untuk memiliki satu baris (atau delegasi anonim) dari kode dieksekusi dengan batas waktu.
TemperamentalClass tc = new TemperamentalClass();
tc.DoSomething(); // normally runs in 30 sec. Want to error at 1 min
Saya mencari solusi yang dapat diimplementasikan secara elegan di banyak tempat di mana kode saya berinteraksi dengan kode temperamental (yang tidak dapat saya ubah).
Selain itu, saya ingin kode "habis waktu" yang menyinggung berhenti dari mengeksekusi lebih lanjut jika memungkinkan.
c#
multithreading
c#-3.0
asynchronous
timeout
chilltemp
sumber
sumber
Jawaban:
Bagian yang benar-benar rumit di sini adalah membunuh tugas yang sudah berjalan lama melalui melewati utas pelaksana dari Aksi kembali ke tempat di mana ia bisa dibatalkan. Saya menyelesaikan ini dengan menggunakan delegasi terbungkus yang membagikan utas untuk membunuh ke variabel lokal dalam metode yang menciptakan lambda.
Saya kirimkan contoh ini, untuk kesenangan Anda. Metode yang sangat menarik bagi Anda adalah CallWithTimeout. Ini akan membatalkan utas jangka panjang dengan membatalkannya, dan menelan ThreadAbortException :
Pemakaian:
Metode statis melakukan pekerjaan:
sumber
Kami banyak menggunakan kode seperti ini di productio n:
Implementasi bersumber terbuka, bekerja secara efisien bahkan dalam skenario komputasi paralel dan tersedia sebagai bagian dari Lokad Shared Libraries
Kode ini masih bermasalah, Anda dapat mencoba dengan program uji kecil ini:
Ada kondisi balapan. Sangat mungkin bahwa ThreadAbortException dinaikkan setelah metode
WaitFor<int>.Run()
dipanggil. Saya tidak menemukan cara yang dapat diandalkan untuk memperbaikinya, namun dengan tes yang sama saya tidak dapat melaporkan masalah dengan jawaban yang diterima TheSoftwareJedi .sumber
Nah, Anda bisa melakukan hal-hal dengan delegasi (BeginInvoke, dengan panggilan balik yang mengatur bendera - dan kode asli menunggu bendera atau batas waktu itu) - tetapi masalahnya adalah sangat sulit untuk mematikan kode yang sedang berjalan. Misalnya, membunuh (atau menjeda) utas berbahaya ... jadi saya tidak berpikir ada cara mudah untuk melakukan ini dengan kuat.
Saya akan memposting ini, tetapi perhatikan ini tidak ideal - tidak menghentikan tugas yang sudah berjalan lama, dan tidak membersihkan dengan benar pada kegagalan.
sumber
Beberapa perubahan kecil pada jawaban hebat Pop Catalin:
Kelebihan telah ditambahkan untuk mendukung pekerja pemberi sinyal untuk membatalkan eksekusi:
sumber
Beginilah cara saya melakukannya:
sumber
Saya baru saja menghilangkan ini sekarang sehingga mungkin perlu beberapa perbaikan, tetapi akan melakukan apa yang Anda inginkan. Ini adalah aplikasi konsol sederhana, tetapi menunjukkan prinsip-prinsip yang diperlukan.
sumber
Bagaimana dengan menggunakan Thread.Join (int timeout)?
sumber