2012-01-05 14 views
9

में एक अपवाद को पकड़ना मेरे पास एक विधि है जो असीमित रूप से निष्पादित करने के लिए कॉलबैक तर्क लेती है, लेकिन कैच ब्लॉक सिंक्रोनस कॉल (this.Submit द्वारा सिंक्रोनस विधि को संदर्भित किसी भी अपवाद को पकड़ने वाला प्रतीत नहीं होता है) ।एक एसिंक्रोनस कॉलबैक

public void Submit(FileInfo file, AnswerHandler callback) 
{ 
    SubmitFileDelegate submitDelegate = new SubmitFileDelegate(this.Submit); 
    submitDelegate.BeginInvoke(file, (IAsyncResult ar) => 
    { 
     string result = submitDelegate.EndInvoke(ar); 
     callback(result); 
    }, null); 
} 

क्या नया धागा फेंक दिया गया अपवाद पकड़ने और इसे मूल धागे पर भेजने का कोई तरीका है? साथ ही, क्या यह async अपवादों को संभालने का "उचित" तरीका है?

try 
{ 
    target.Submit(file, (response) => 
    { 
     // do stuff 
    }); 
} 
catch (Exception ex) 
{ 
    // catch stuff 
} 

लेकिन वहाँ यह करने के लिए एक और अधिक उचित या सुरुचिपूर्ण तरीका है: तो यह इस तरह कहा जाता है किया जा सकता है (यह मानते हुए अपवाद समस्या का समाधान हो जाता है) मैं अपने कोड लिखा?

+0

अपने पहले कोड नमूने में कैच ब्लॉक एक अपवाद कॉलबैक द्वारा या EndInvoke द्वारा फेंका पकड़ लेंगे।आपके दूसरे कोड नमूने में कैच ब्लॉक सबमिटफाइलडिलेगेट कन्स्ट्रक्टर या BeginInvoke द्वारा फेंक दिया गया कोई भी अपवाद पकड़ लेगा। कौन सा ऐसा नहीं कर रहा है जो आप उम्मीद करते हैं/चाहते हैं? – dgvid

+0

ओह, इसे हटाने के लिए भूल गए। मैं चाहता हूं कि दूसरा सही तरीके से काम करे, लेकिन फिलहाल, न तो है। – kevmo314

+0

क्या आप दिखा सकते हैं कि 'SubmitFileDelegate' कैसे परिभाषित किया गया है? – GolfWolf

उत्तर

8

इसे 'सबसे अच्छा अभ्यास' समाधान नहीं है, लेकिन मुझे लगता है यह एक साधारण एक है कि काम करना चाहिए है।

इसके बजाय प्रतिनिधि के रूप में

private delegate string SubmitFileDelegate(FileInfo file); 

परिभाषित होने के रूप में

private delegate SubmitFileResult SubmitFileDelegate(FileInfo file); 

यह परिभाषित करने और इस प्रकार SubmitFileResult को परिभाषित:

public class SubmitFileResult 
{ 
    public string Result; 
    public Exception Exception; 
} 

फिर, विधि वास्तव में है कि फ़ाइल सबमिशन (प्रश्न में नहीं दिखाया गया) इस तरह परिभाषित किया जाना चाहिए:

private static SubmitFileResult Submit(FileInfo file) 
{ 
    try 
    { 
     var submissionResult = ComplexSubmitFileMethod(); 

     return new SubmitFileResult { Result = submissionResult }; 
    } 
    catch (Exception ex) 
    { 
     return new SubmitFileResult {Exception = ex, Result = "ERROR"}; 
    } 
} 

इस तरह, आप परिणाम वस्तु की जांच करेंगे, देखें कि इसका परिणाम या अपवाद फ़ील्ड सेट है या नहीं और तदनुसार कार्य करें।

+0

हालांकि यह कॉल तुल्यकालिक नहीं है? मैंने BeginInvoke कॉलबैक में कोशिश/पकड़ने की कोशिश की (और आपके उदाहरण के साथ हालांकि) लेकिन यह अपवाद को पकड़ने के लिए प्रतीत नहीं हुआ। – kevmo314

+0

नहीं, यह तुल्यकालिक नहीं है। कृपया ध्यान दें कि दो 'सबमिट' विधियां हैं: मैंने ऊपर वर्णित एक (जिसे 'SubmitFileDelegate' परिभाषा से मेल खाना है) और जिस प्रश्न में आपने प्रस्तुत किया है, वह 'BeginInvoke का दूसरा है (जिसका अर्थ है कि यह एक async कॉल है)। – GolfWolf

3

संक्षेप में, नहीं।

जब आप submitDelegate.BeginInvoke पर कॉल करते हैं, तो यह नए थ्रेड, रिटर्न, और तुरंत आपके प्रयास/पकड़ ब्लॉक से बाहर निकलता है (जबकि नया धागा पृष्ठभूमि में चलता है)।

AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(YourException);

यह आवेदन डोमेन सब कुछ पकड़ेगा, तथापि (न सिर्फ अपने async विधि):

हालांकि, आप सभी बिना क्रिया अपवाद इस तरह पकड़ सकते थे।

+0

क्या अपवादों को संभालने का कोई पसंदीदा तरीका है? मुझे कॉलबैक जेएस दुनिया से फ़ंक्शन (त्रुटि, परिणाम) {} जैसी कुछ चीज़ होने के लिए उपयोग किया जाता है, लेकिन मैंने सी # कोड नमूने में ऐसा कुछ नहीं देखा है, इसलिए मुझे यकीन नहीं है कि यह कैसे है यह सी # में किया जाना चाहिए ... एस – kevmo314

+0

@ w0lf का जवाब मूल रूप से है; आप अपवाद को लपेटते हैं जो आपके प्रतिक्रिया प्रकार के भीतर होता है और इसे पूरा होने के बाद बाहर खींचता है। –

9

यदि आप .NET 4.0 को लक्षित कर रहे हैं, तो आप नई कार्य समांतर लाइब्रेरी का उपयोग कर सकते हैं और Task ऑब्जेक्ट की Exception संपत्ति का निरीक्षण कर सकते हैं।

public Task Submit(FileInfo file) 
{ 
    return Task.Factory.StartNew(() => DoSomething(file)); 
} 

private void DoSomething(FileInfo file) 
{ 
    throw new Exception(); 
} 

तो इस तरह इसका इस्तेमाल:

Submit(myFileInfo).ContinueWith(task => 
{ 
    // Check task.Exception for any exceptions. 

    // Do stuff with task.Result 
}); 

जहां DoSomething विधि आप एसिंक्रोनस रूप से कॉल करना चाहते है, और प्रतिनिधि आप ContinueWith को पारित अपने कॉलबैक है।

अधिक TPL में अपवाद संचालन के बारे में जानकारी यहां पाया जा सकता है: http://msdn.microsoft.com/en-us/library/dd997415.aspx

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