ऐसा करने का तरीका रद्दीकरण टोकन और नया रद्दीकरण मॉडल के साथ है। नया रद्दीकरण मॉडल कई प्रकारों में .NET Framework में एकीकृत है। सबसे महत्वपूर्ण सिस्टम हैं। थ्रेडिंग। कार्य, सिस्टम .Treading.Tasks.Task, System.Threading.Tasks.Task और System.Linq.ParallelEnumerable।
यहां आपकी समस्या का एक उदाहरण है। यह कोड हमेशा डेडलॉक होगा क्योंकि कॉलिंग कोड पहले लॉक लेता है और फिर मृतक कार्य उसी लॉक को प्राप्त करने का प्रयास करता है।
public void Example()
{
object sync = new Object();
lock (sync)
{
CancellationTokenSource canceller = new CancellationTokenSource();
ManualResetEvent started = new ManualResetEvent(false);
Task deadlocked = Task.Factory.StartNew(() =>
{
started.Set();
// EVIL CODE: This will ALWAYS deadlock
lock(sync) { };
},
canceller.Token);
// Make sure task has started.
started.WaitOne();
canceller.Cancel();
try
{
// Wait for task to cancel.
deadlocked.Wait();
}
catch (AggregateException ex)
{
// Ignore canceled exception. SIMPLIFIED!
if (!(ex.InnerException is TaskCanceledException))
throw;
}
}
}
टीपीएल में कार्य रद्दीकरण सहकारी है। दूसरे शब्दों में यह हमेशा डेडलॉक होगा क्योंकि रद्दीकरण टोकन को रद्द करने के लिए कुछ भी सेट नहीं किया जाता है क्योंकि टास्क थ्रेड लॉक हो जाता है।
इस के चारों ओर एक तरीका नहीं है लेकिन यह अभी भी अविश्वसनीय कोड के लेखकों पर निर्भर करता है सही काम करने के लिए:
public static void Example2()
{
Mutex sync = new Mutex(true);
CancellationTokenSource canceller = new CancellationTokenSource();
bool started = false;
Task deadlocked = Task.Factory.StartNew(() =>
{
started = true;
// EVIL CODE: This will ALWAYS deadlock
WaitHandle.WaitAny(new WaitHandle[] { canceller.Token.WaitHandle, sync });
},
canceller.Token);
// Make sure task has started.
while (!started) { }
canceller.Cancel();
try
{
// Wait for task to cancel.
deadlocked.Wait();
}
catch (AggregateException ex)
{
// Ignore canceled exception. SIMPLIFIED!
if (!(ex.InnerException is TaskCanceledException))
throw;
}
}
अंक नोट करने के लिए; रद्दीकरण सहकारी है। आप एक संभाल पाने के लिए टोकन.WaitHandle का उपयोग कर सकते हैं और अन्य सिंक्रनाइज़ेशन primitives के हैंडल (एस) के साथ इसके साथ इंतजार कर सकते हैं। म्यूटेक्स मॉनीटर (या लॉक) से बहुत धीमा है।
वास्तव में यदि आप कोऑपरेटिव रद्दीकरण को लागू करने के लिए पर्याप्त कोड के लेखक पर भरोसा नहीं करते हैं तो मैं एक ही थ्रेड पर अपने ऐपडोमेन के अंदर दौड़ने की संवेदना पर सवाल उठाऊंगा।
अधिक विस्तार के लिए देखें:
http://msdn.microsoft.com/en-us/library/dd997364.aspx
http://msdn.microsoft.com/en-us/library/dd537607.aspx
http://msdn.microsoft.com/en-us/library/ee191552.aspx
स्रोत
2010-05-06 06:43:16
धन्यवाद, यह उपयोगी जानकारी है। हालांकि, मैं इस धारणा के तहत था कि रद्दीकरण अनुरोध को सुनने के लिए कार्य पर निर्भर है और यदि आप पूरी तरह से पूरा नहीं कर पा रहे हैं तो ऑपरेशन कैंक्शनल अपवाद को अपने आप पर फेंक दें। जब मैं आज दोपहर का मौका मिलता हूं तो मैं आपका कोड आज़माउंगा। –
पहले लिंक से, "श्रोताओं को मतदान, कॉलबैक पंजीकरण, या प्रतीक्षा हैंडल पर प्रतीक्षा करके रद्दीकरण अनुरोधों के बारे में अधिसूचित किया जा सकता है।" तो प्रभावी ढंग से कार्य। प्रतीक्षा सुनने के कारण होता है। –
देखें: http://stackoverflow.com/questions/2293976/how-and-if-to-write-a-single-consumer-queue-using-the-task-parallel-library/2779208#2779208 के उदाहरण के लिए रद्दीकरण की जांच करने और इसका जवाब देने के लिए IsCancellationRequested का उपयोग करना। –