यदि संभव हो तो धागे को रोकना और बाधित करना टालना चाहिए क्योंकि यह एक चल रहे कार्यक्रम की स्थिति को दूषित कर सकता है। उदाहरण के लिए, कल्पना करें कि आपने उन थ्रेड को निरस्त कर दिया है जो संसाधनों के लिए खुले ताले रख रहे थे, ये ताले कभी जारी नहीं किए जाएंगे।
इसके बजाय, ताकि धागे कर सकते हैं एक दूसरे के साथ सहयोग करने और इतने अवरुद्ध और शान से अनब्लॉक करने, जैसे संभाल एक संकेतन तंत्र का उपयोग करें:
private readonly AutoResetEvent ProcessEvent = new AutoResetEvent(false);
private readonly AutoResetEvent WakeEvent = new AutoResetEvent(false);
public void Do()
{
Thread th1 = new Thread(ProcessSomething);
th1.IsBackground = false;
th1.Start();
ProcessEvent.WaitOne();
Console.WriteLine("Processing started...");
Thread th2 = new Thread(() => WakeEvent.Set());
th2.Start();
th1.Join();
Console.WriteLine("Joined");
}
private void ProcessSomething()
{
try
{
Console.WriteLine("Processing...");
ProcessEvent.Set();
}
finally
{
WakeEvent.WaitOne();
Console.WriteLine("Woken up...");
}
}
अद्यतन
काफी एक दिलचस्प निम्न स्तर मुद्दा। हालांकि Abort()
दस्तावेज है, Interrupt()
बहुत कम है।
आपके प्रश्न का संक्षिप्त उत्तर नहीं है, आप Abort
या Interrupt
पर कॉल करके अंत में ब्लॉक में थ्रेड नहीं जगा सकते हैं।
आखिरकार ब्लॉक में धागे को निरस्त या बाधित करने में सक्षम नहीं है, डिज़ाइन द्वारा बस, अंत में ब्लॉक को चलाने की संभावना होती है जैसा आप उम्मीद करेंगे। यदि आप आखिरकार ब्लॉक में थ्रेड को रोक सकते हैं और बाधित कर सकते हैं तो इसमें क्लीनअप दिनचर्या के लिए अनपेक्षित परिणाम हो सकते हैं, और इसलिए एप्लिकेशन को भ्रष्ट स्थिति में छोड़ दें - अच्छा नहीं।
थ्रेड बाधा के साथ मामूली बारीकियों, यह है कि अंत में ब्लॉक में प्रवेश करने से पहले किसी भी समय थ्रेड के खिलाफ एक बाधा जारी की जा सकती है, लेकिन जब यह SleepWaitJoin
स्थिति (यानी अवरुद्ध नहीं) में नहीं था। इस उदाहरण में अगर अंत में ब्लॉक में अवरुद्ध कॉल था तो यह तुरंत ThreadInterruptedException
फेंक देगा और अंत में ब्लॉक से बाहर हो जाएगा। अंत में ब्लॉक संरक्षण इसे रोकता है।
साथ ही अंत में ब्लॉक में सुरक्षा, यह ब्लॉक और सीईआर (Constrained Execution Region) को भी कोशिश करने के लिए विस्तारित करता है जिसे उपयोगकर्ता कोड में कॉन्फ़िगर किया जा सकता है ताकि किसी क्षेत्र को निष्पादित किए जाने तक अपवादों की एक श्रृंखला को रोका जा सके - महत्वपूर्ण ब्लॉक के लिए बहुत उपयोगी कोड का पूरा होना चाहिए और निरस्तीकरण में देरी होनी चाहिए।
अपवाद (कोई इरादा नहीं है) इसे Rude Aborts कहा जाता है। ये सीएलआर होस्टिंग पर्यावरण द्वारा उठाए गए ThreadAbortExceptions
हैं। ये आखिरकार ब्लॉक कर सकते हैं और ब्लॉक को बाहर निकालने के लिए पकड़ सकते हैं, लेकिन सीईआर नहीं। उदाहरण के लिए, सीएलआर धागे के जवाब में रूड एबॉर्ट्स बढ़ा सकता है, जिसने अपने काम को बाहर करने के लिए बहुत लंबा समय लेने का फैसला किया है। SQL सर्वर CLR के भीतर कोई ऐपडोमेन या कोड निष्पादित करने का प्रयास करते समय। आपके विशेष उदाहरण में, जब आपका एप्लिकेशन बंद हो जाता है और ऐपडोमेन अनलोड हो जाता है, तो सीएलआर नींद के धागे पर एक अशिष्ट गर्भपात जारी करेगा क्योंकि ऐपडोमेन अनलोड लोडआउट होगा।
अंततः ब्लॉक में निरंतर अवरोध और बाधा उपयोगकर्ता कोड में नहीं होने वाली है, लेकिन दोनों मामलों के बीच थोड़ा अलग व्यवहार है।
बीच में बंद करें
जब एक अंत में ब्लॉक में एक धागे पर Abort
बुला, बुला धागा अवरुद्ध है। यह documented है:
धागा कॉल बीच में बंद करें अगर धागा है कि निरस्त किया जा रहा है इस तरह के एक पकड़ ब्लॉक के रूप में कोड, के एक संरक्षित क्षेत्र में है, अंत में ब्लॉक, या बाधित निष्पादन क्षेत्र अवरुद्ध कर सकता है। यानी इसे यहाँ बंद हो जाता है और तुरंत आगे बढ़ना नहीं है
- बुला धागा एक
Abort
जारी लेकिन यहाँ ब्लॉक जब तक अंत में ब्लॉक से बाहर निकल गया है जाएगा:
बीच में बंद करें मामले में अगर नींद अनंत नहीं था Join
कथन के लिए।
कैली थ्रेड का राज्य AbortRequested
पर सेट है।
कैली सो रही है। जब कैली जागता है, क्योंकि इसमें AbortRequested
की स्थिति होती है तो यह आखिरकार ब्लॉक कोड निष्पादित करना जारी रखेगी और फिर "वाष्पीकरण" यानी बाहर निकलेंगी। जब निरस्त धागा अंततः ब्लॉक छोड़ देता है: कोई अपवाद नहीं उठाया जाता है, अंत में ब्लॉक को निष्पादित करने के बाद कोई कोड नहीं होता है, और धागा का राज्य Aborted
होता है। कॉलिंग थ्रेड अनब्लॉक किया गया है, Join
कथन जारी है और तुरंत कहा जाता है क्योंकि बुलाया गया थ्रेड निकल गया है। तो एक अनंत नींद के साथ अपने उदाहरण को देखते हुए बुला धागा चरण 1
इंटरप्ट
बाधा मामले में पर हमेशा के लिए ब्लॉक अगर नींद अनंत नहीं था होगा:
इतना अच्छी तरह से प्रलेखित नहीं ...
- बुला धागा एक
Interrupt
और को क्रियान्वित करने के लिए जारी जारी करेगा।
- कॉलिंग थ्रेड
Join
कथन पर अवरुद्ध होगा।
- कैली थ्रेड के पास अगले ब्लॉकिंग कॉल पर अपवाद बढ़ाने के लिए अपना राज्य सेट है, लेकिन महत्वपूर्ण रूप से यह आखिरकार ब्लॉक में है, इसलिए इसे अनब्लॉक नहीं किया गया है।
- कैली सो रही है।
- जब कैली जागता है, तो यह अंततः ब्लॉक को निष्पादित करना जारी रखेगा।
- जब बाधित थ्रेड अंततः ब्लॉक छोड़ देता है तो यह अगले ब्लॉकिंग कॉल पर
ThreadInterruptedException
फेंक देगा (नीचे कोड उदाहरण देखें)।
- बुला धागा "मिलती है" और के रूप में बुलाया धागा से बाहर निकल गया है, हालांकि, बिना क्रिया
ThreadInterruptedException
चरण 6 में अब प्रक्रिया चपटा है जारी है ...
तो फिर एक अनंत नींद के साथ अपने उदाहरण को देखते हुए, बुला धागा हमेशा के लिए अवरुद्ध कर देगा, लेकिन कदम पर 2.
सारांश
इसलिए हालांकि Abort
और Interrupt
थोड़ा अलग व्यवहार है, वे बुलाया सूत्र में दोनों परिणाम हमेशा के लिए सो जाएगा, और बुला धागा हमेशा के लिए अवरुद्ध (मेंआपका उदाहरण)।
केवल एक असभ्य बीच में बंद करें एक अंत में ब्लॉक से बाहर निकलने का अवरुद्ध धागा मजबूर कर सकते हैं, और इनमें से केवल CLR से ही उठाया जा सकता है (आप भी ThreadAbortException.ExceptionState
लुढ़का करने के लिए प्रतिबिंब का उपयोग नहीं कर सकते हैं के रूप में यह AbortReason
प्राप्त करने के लिए एक आंतरिक CLR कॉल करता है - वहां आसानी से बुराई होने का कोई मौका नहीं है ...)।
सीएलआर उपयोगकर्ता कोड को अंततः ब्लॉकों को अपने स्वयं के अच्छे से बाहर निकलने के कारण रोकता है - यह दूषित राज्य को रोकने में मदद करता है।
Interrupt
साथ थोड़ा अलग व्यवहार का एक उदाहरण के लिए:
internal class ThreadInterruptFinally
{
public static void Do()
{
Thread t = new Thread(ProcessSomething) { IsBackground = false };
t.Start();
Thread.Sleep(500);
t.Interrupt();
t.Join();
}
private static void ProcessSomething()
{
try
{
Console.WriteLine("processing");
}
finally
{
Thread.Sleep(2 * 1000);
}
Console.WriteLine("Exited finally...");
Thread.Sleep(0); //<-- ThreadInterruptedException
}
}
मैं सवाल का जवाब पता नहीं है, लेकिन मैं * है * पता है कि एक सामान्य नियम के रूप में मैं से बचने के 'इंटरप्ट () 'धागे के बीच संकेत के लिए एक तंत्र के रूप में। बहुत अधिक अनुमानित एपीआई हैं- 'मॉनिटर', '{मैनुअल | ऑटो} रीसेट इवेंट ', आदि –
मैं अंततः इंटरप्ट/एबॉर्ट काम नहीं करता है और एमएसडीएन विपरीत कहने पर क्यों कोई स्पष्टीकरण/दस्तावेज़ीकरण की तलाश में था। मेरा उदाहरण अधिक जटिल प्रकार का परामर्शदाता है और मैं अब सुझाव के रूप में इसे कमरांड के लिए पढ़ रहा हूं। – Marek
दो प्रकार के थ्रेड एबॉर्ट्स हैं। दोस्ताना एक आखिरकार ब्लॉक में कोड को बाधित नहीं करेगा। असभ्य रूप से एक आक्रमण किया जाता है जब प्रक्रिया उस थ्रेड पर बंद हो जाती है जिसमें IsBackground सत्य के बराबर है या जब यह एक अनचाहे अपवाद पर समाप्त हो रहा है। अब इससे कोई फर्क नहीं पड़ता कि कोड कठोर रूप से बाधित हो गया है। –