2011-12-30 13 views
23

मेरे पास एक तरीका है जो कुछ कार्य बनाता है, और फिर लौटने से पहले WaitAll के साथ उन पर प्रतीक्षा करता है। समस्या यह है कि, यदि उन कार्यों को रद्द कर दिया गया है, तो WaitAll AggregateException फेंकता है जिसमें बहुत सारे TaskCanceledException एस हैं।कार्यक्षेत्र अपवादों को फेंक दिए बिना मैं कार्यों पर कैसे इंतजार कर सकता हूं?

इसका मतलब है कि WaitAll दो अलग-अलग परिस्थितियों में अपवाद फेंक देगा:

  • अपवाद है कि एक वास्तविक त्रुटि संकेत मिलता है। इसका मतलब है कि एक ऐसी स्थिति थी जिसे हम नहीं जानते थे कि कैसे संभालना है; जब तक वे अंततः प्रक्रिया को समाप्त नहीं करते हैं, तब तक उन्हें अनचाहे अपवादों के रूप में प्रचार करने की आवश्यकता होती है।
  • अपवाद जो इंगित करते हैं कि उपयोगकर्ता ने एक रद्द बटन पर क्लिक किया था। इसका मतलब है कि कार्य रद्द कर दिया गया था और साफ किया गया था, और कार्यक्रम सामान्य रूप से चलना जारी रखना चाहिए।

बाद वर्गाकार एक vexing exception की परिभाषा में हो: यह एक अपवाद एक पूरी तरह गैर असाधारण परिस्थिति में फेंक दिया है, तो मैं आदेश सामान्य नियंत्रण प्रवाह फिर से शुरू करने में उसे पकड़ने के लिए है। सौभाग्य से पकड़ना आसान है, है ना? बस catch (AggregateException) जोड़ें और - ओह रुको, वही वही प्रकार है जो घातक त्रुटि होने पर फेंक दिया जाता है।

मुझे लौटने से पहले कार्यों को समाप्त करने की प्रतीक्षा करने की आवश्यकता है (मुझे यह जानने की ज़रूरत है कि वे अब अपने डेटाबेस कनेक्शन, फ़ाइल हैंडल या अन्य किसी भी चीज़ का उपयोग नहीं कर रहे हैं), इसलिए मुझे WaitAll या कुछ चाहिए समान। और यदि किसी भी कार्य में गलती हुई है, तो मैं उन अपवादों को अनचाहे अपवादों के रूप में प्रचारित करना चाहता हूं। मैं सिर्फ रद्द करने के लिए अपवाद नहीं चाहता हूं।

मैं रद्द किए गए कार्यों के लिए अपवाद फेंकने से WaitAll को कैसे रोक सकता हूं?

+0

उपयोग अधिभार है कि एक CancellationToken लेता चला जाता है। –

+0

@ हंसपैसेंट, उस अधिभार के लिए दस्तावेज़ वास्तव में यह नहीं कहते हैं कि यह टोकन का उपयोग करता है। क्या यह उस टोकन से जुड़े टास्ककैंक्लेड अपवादों को अनदेखा कर देगा, या टोकन रद्द होने पर यह जल्दी ही वापस आ जाएगा? मुझे तब तक वापस आने की ज़रूरत नहीं है जब तक कि सभी कार्यों को बंद नहीं किया जाता है। –

+1

आप कार्य रद्द करने के लिए रद्द करने के लिए रद्द कर सकते हैं। और विशिष्ट ऑपरेशन कैंसल अपवाद को फ़िल्टर करें जिसे आप अब प्राप्त करेंगे। –

उत्तर

28

AggregateExceptionHandle विधि प्रदान करता है जो इन परिस्थितियों के लिए उपयोग किया जा सकता है। उदाहरण के लिए आप TaskCanceledException अनदेखी करने के लिए चाहते हैं, तो आप कर सकते हैं:

var all = new AggregateException(
    new NullReferenceException(), 
    new TaskCanceledException(), 
    new TaskCanceledException(), 
    new InvalidOperationException(), 
    new TaskCanceledException()); 

try 
{ 
    throw all; 
} 
catch (AggregateException errors) 
{ 
    errors.Handle(e => e is TaskCanceledException); 
} 

सभी अपवादों प्रकार TaskCanceledException के हैं, तो Handle विधि किसी भी अपवाद नहीं होगा; अन्यथा एक नया AggregateException जिसमें केवल अनचाहे अपवाद शामिल किए जाएंगे।

1

पर João Angelo's suggestion आधार पर, यहाँ एक टास्क वर्ग विस्तार

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading; 
using System.Threading.Tasks; 

namespace MySharedLibrary.Extensions 
{ 
    public static class TaskExtensions 
    { 

     // This code is based João Angelo's stackoverflow suggestion https://stackoverflow.com/a/8681687/378115 

     // Use this when a CancellationTokenSource is used 
     public static void SafeWait(this Task TargetTask, CancellationTokenSource TargetTaskCancellationTokenSource) 
     { 
      if (TargetTaskCancellationTokenSource.IsCancellationRequested == false) 
      { 
       TargetTaskCancellationTokenSource.Cancel(); 
      } 
      SafeWait(TargetTask); 
     } 

     // Use this when no CancellationTokenSource is used 
     public static void SafeWait(this Task TargetTask) 
     { 
      try 
      { 
       if (TargetTask.IsCanceled == false) 
       { 
        TargetTask.Wait(); 
       } 
      } 
      catch (AggregateException errors) 
      { 
       errors.Handle(e => e is TaskCanceledException); 
      } 
     } 

    } 
} 
संबंधित मुद्दे

 संबंधित मुद्दे