Computer >> कंप्यूटर ट्यूटोरियल >  >> प्रोग्रामिंग >> C#

C# में async void मेथड द्वारा फेंके गए एक्सेप्शन को कैसे पकड़ें

सिंक्रोनस C# कोड में, एक्सेप्शन कॉल स्टैक तक प्रसारित होते हैं जब तक वे एक उपयुक्त catch ब्लॉक तक नहीं पहुंच जाते जो एक्सेप्शन को संभाल सके। हालांकि, एसिंक्रोनस मेथड्स में एक्सेप्शन हैंडलिंग सीधी नहीं है।

C# में एक एसिंक्रोनस मेथड के तीन प्रकार के रिटर्न मान हो सकते हैं: void, Task, और Task<T>। जब Task या Task<T> रिटर्न टाइप वाले एसिंक्रोनस मेथड में एक्सेप्शन होता है, तो एक्सेप्शन ऑब्जेक्ट AggregateException के इंस्टेंस में लपेटा जाता है और Task ऑब्जेक्ट से जुड़ जाता है।

यदि कई एक्सेप्शन फेंके जाते हैं, तो उन सभी को Task ऑब्जेक्ट में संग्रहीत किया जाता है।

समस्या: async void एक्सेप्शन पकड़े नहीं जा सकते


// खतरनाक: async void - एक्सेप्शन क्रैश करेगा एप्लिकेशन
public async void BadAsyncVoid()
{
    throw new InvalidOperationException("Oops!");
}

// कॉलर इसे पकड़ नहीं सकता
try
{
    BadAsyncVoid(); // एक्सेप्शन यहां नहीं पकड़ा जाएगा!
}
catch (Exception ex)
{
    // कभी नहीं पहुंचेगा
}

समाधान: async Task का उपयोग करें

// सही: async Task - एक्सेप्शन Task में कैप्चर होता है
public async Task GoodAsyncTask()
{
    throw new InvalidOperationException("Oops!");
}

// कॉलर इसे पकड़ सकता है
public async Task Caller()
{
    try
    {
        await GoodAsyncTask();
    }
    catch (InvalidOperationException ex)
    {
        Console.WriteLine($"Caught: {ex.Message}");
    }
}

उदाहरण: सही एक्सेप्शन हैंडलिंग

static async Task Main(string[] args)
{
    await DoSomething();
    Console.ReadLine();
}

public static async Task Foo()
{
    throw new ArgumentNullException("Parameter cannot be null");
}

public static async Task DoSomething()
{
    try
    {
        await Foo();
    }
    catch (ArgumentNullException ex)
    {
        Console.WriteLine($"Caught: {ex.Message}");
        Console.WriteLine($"Stack trace: {ex.StackTrace}");
    }
}

आउटपुट

Caught: Parameter cannot be null
Stack trace: at Program.Foo() in ...\Program.cs:line 37
   at Program.DoSomething() in ...\Program.cs:line 44

एकाधिक एक्सेप्शन हैंडलिंग (Task.WhenAll)

public static async Task HandleMultipleTasks()
{
    var task1 = Task.Run(() => { throw new ArgumentException("Task 1 failed"); });
    var task2 = Task.Run(() => { throw new InvalidOperationException("Task 2 failed"); });
    
    try
    {
        await Task.WhenAll(task1, task2);
    }
    catch (Exception ex) when (ex is AggregateException aggEx)
    {
        foreach (var inner in aggEx.InnerExceptions)
        {
            Console.WriteLine($"Inner exception: {inner.GetType().Name} - {inner.Message}");
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Single exception: {ex.Message}");
    }
}

async void के वैध उपयोग

  • इवेंट हैंडलर्स (जैसे button_Click)
  • टॉप-लेवल एंट्री पॉइंट्स जहां कोई कॉलर नहीं है

सर्वोत्तम अभ्यास

  1. लगभग हमेशा async Task लौटाएं - async void से बचें
  2. इवेंट हैंडलर्स के लिए async void स्वीकार्य है
  3. टॉप-लेवल प्रोग्राम में async Task Main() का उपयोग करें
  4. एक्सेप्शन को अवेट करें - Task.Run बिना अवेट के न करें
  5. ConfigureAwait(false) लाइब्रेरी कोड में उपयोग करें

मूल कोड में समस्या

मूल उदाहरण static async Task Main का उपयोग करता है जो C# 7.1+ में ठीक है, लेकिन Task.Delay(1000) को अवेट नहीं करता - यह केवल टास्क बनाता है और उसे अनदेखा करता है। सही उपयोग: await Task.Delay(1000)।

  1. - पायथन में ArithmeticError एक्सेप्शन कैसे पकड़ें?

    ArithmeticError एक्सेप्शन उन सभी एरर्स के लिए बेस क्लास है जो संख्यात्मक गणनाओं के लिए होते हैं। यह उन बिल्ट-इन एक्सेप्शन्स के लिए बेस क्लास है जैसे: OverflowError, ZeroDivisionError, FloatingPointError। हम दिए गए कोड में एक्सेप्शन को निम्न प्रकार से पकड़ सकते हैं: उदाहरण import sys try: 7/0 exc

  1. - पायथन में IOError एक्सेप्शन कैसे पकड़ें?

    IOError एक्सेप्शन यह एक एरर है जो तब उठाया जाता है जब इनपुट/आउटपुट ऑपरेशन विफल होता है, जैसे प्रिंट स्टेटमेंट या open() फ़ंक्शन जब किसी ऐसी फ़ाइल को खोलने का प्रयास करता है जो मौजूद नहीं है। यह ऑपरेटिंग सिस्टम से संबंधित एरर्स के लिए भी उठाया जाता है। यदि दिए गए कोड को try ब्लॉक में लिखा जाता है, तो

  1. - पायथन में KeyError एक्सेप्शन कैसे पकड़ें?

    KeyError तब उठाया जाता है जब कोई मान डिक्शनरी की कुंजी के रूप में नहीं मिलता। दिए गए कोड को एक्सेप्शन पकड़ने और उसका प्रकार खोजने के लिए निम्न प्रकार से फिर से लिखा गया है। उदाहरण import sys try: s = {a:5, b:7}[c] except: print(sys.exc_info()) आउटपुट (, KeyError(c,), )