कैच ब्लॉक में इंतजार


85

मेरे पास निम्नलिखित कोड हैं:

WebClient wc = new WebClient();
string result;
try
{
  result = await wc.DownloadStringTaskAsync( new Uri( "http://badurl" ) );
}
catch
{
  result = await wc.DownloadStringTaskAsync( new Uri( "http://fallbackurl" ) );
}

मूल रूप से मैं एक URL से डाउनलोड करना चाहता हूं और जब यह अपवाद के साथ विफल होता है तो मैं दूसरे URL से डाउनलोड करना चाहता हूं। दोनों समय async बेशक। हालाँकि कोड संकलित नहीं करता है, क्योंकि

CS1985 त्रुटि: कैच क्लॉज के शरीर में प्रतीक्षा नहीं की जा सकती

ठीक है, यह किसी भी कारण से निषिद्ध है लेकिन यहां सही कोड पैटर्न क्या है?

संपादित करें:

अच्छी खबर यह है कि C # 6.0 की संभावना कैच और अंत में ब्लॉक दोनों में प्रतीक्षा कॉल की अनुमति होगी

जवाबों:


103

अद्यतन: C # 6.0 पकड़ने में प्रतीक्षा का समर्थन करता है


पुराना उत्तर : आप उस कोड को एक झंडे का उपयोग करके ब्लॉक awaitसे स्थानांतरित करने के लिए फिर से लिख सकते हैं catch:

WebClient wc = new WebClient();
string result = null;
bool downloadSucceeded;
try
{
  result = await wc.DownloadStringTaskAsync( new Uri( "http://badurl" ) );
  downloadSucceeded = true;
}
catch
{
  downloadSucceeded = false;
}

if (!downloadSucceeded)
  result = await wc.DownloadStringTaskAsync( new Uri( "http://fallbackurl" ) );

7
धन्यवाद svick, यह काफी स्पष्ट है, कुछ बेहतर है, और अधिक async से जुड़ा है?
ग्योगी बलेसी

मुझे नहीं लगता कि ऐसा कुछ भी मौजूद है।
१२:१२ पर svick

3
आपके मामले में, आप कार्य निरंतरता का भी उपयोग कर सकते हैं। लेकिन कोड के svickउत्तर में कोड निरंतरता का उपयोग करके कोड की तुलना में क्लीनर है।
स्टीफन क्लीयर

16
यदि आपको कॉलस्टैक खोए बिना अपवाद को फिर से उखाड़ फेंकने की आवश्यकता है, तो आप System.Runtime.ExceptionServices.ExceptionDispatchInfoस्थैतिक वर्ग का उपयोग भी कर सकते हैं । बस ExceptionDispatchInfo.Capture(ex)अपने कैच ब्लॉक में कॉल करें और स्थानीय वैरिएबल में रिटर्न वैल्यू, कैप्चर किए गए अपवाद को स्टोर करें। एक बार जब आप अपने async कोड के साथ कर लेते हैं, तो आप उपयोग कर सकते हैं capturedException.Throw()जो मूल अपवाद को ठीक से पुनर्व्यवस्थित करेगा।
एटिएन माहू

जबरदस्त तकनीक
ज़िया उर रहमान

24

कैच ब्लॉक में प्रतीक्षारत करना अब रोसलिन के अंतिम उपयोगकर्ता पूर्वावलोकन के रूप में संभव है जैसा कि यहां दिखाया गया है (कैच में प्रतीक्षा के तहत सूचीबद्ध / अंत में) और सी # 6 में शामिल किया जाएगा।

सूचीबद्ध उदाहरण है

trycatch { await … } finally { await … }

अपडेट: नया लिंक जोड़ा गया, और यह C # 6 में होगा


9

यह काम करने लगता है।

        WebClient wc = new WebClient();
        string result;
        Task<string> downloadTask = wc.DownloadStringTaskAsync(new Uri("http://badurl"));
        downloadTask = downloadTask.ContinueWith(
            t => {
                return wc.DownloadStringTaskAsync(new Uri("http://google.com/")).Result;
            }, TaskContinuationOptions.OnlyOnFaulted);
        result = await downloadTask;

6

इसे आजमाइए:

         try
        {
            await AsyncFunction(...);
        }

        catch(Exception ex)
        { 
            Utilities.LogExceptionToFile(ex).Wait();
            //instead of "await Utilities.LogExceptionToFile(ex);"
        }

(देखें Wait()अंत)


4

C # 6.0 का उपयोग करें। इस लिंक को देखें

public async Task SubmitDataToServer()
{
  try
  {
    // Submit Data
  }
  catch
  {
    await LogExceptionAsync();
  }
  finally
  {
    await CloseConnectionAsync();
  }
}

1

पैटर्न जिसका उपयोग मैं फ़ॉलबैक कार्य पर प्रतीक्षा करने के बाद अपवाद को पुनर्जीवित करने के लिए करता हूं:

ExceptionDispatchInfo capturedException = null;
try
{
  await SomeWork();
}
catch (Exception e)
{
  capturedException = ExceptionDispatchInfo.Capture(e);
}

if (capturedException != null)
{
  await FallbackWork();
  capturedException.Throw();
}

1

आप इस प्रकार एक लंबोदर अभिव्यक्ति का उपयोग कर सकते हैं:

  try
    {
        //.....
    }
    catch (Exception ex)
    {
        Action<Exception> lambda;

        lambda = async (x) =>
        {
            // await (...);
        };

        lambda(ex);
    }

यह लैम्ब्डा बनाता है async void, जिसका उपयोग नहीं किया जाना चाहिए, जब तक कि आपके पास न हो।
svick

0

आप एक के awaitबाद कैच ब्लॉक के बाद डाल सकते हैं label, और एक gotoकोशिश ब्लॉक में डाल सकते हैं । (नहीं, वास्तव में! गोटो वह बुरा नहीं है!)


0

इसी तरह के उदाहरण में, मैं कैच ब्लॉक में इंतजार नहीं कर पा रहा था। हालाँकि, मैं एक ध्वज सेट करने में सक्षम था, और यदि कोई कथन में ध्वज का उपयोग करता है (नीचे कोड)

---------------------------------------...

boolean exceptionFlag = false; 

try 
{ 
do your thing 
} 
catch 
{ 
exceptionFlag = true; 
} 

if(exceptionFlag == true){ 
do what you wanted to do in the catch block 
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.