c# - सकत - इंतजार किए बिना सी#में एसिंक विधि को सुरक्षित रूप से कैसे कॉल करें




मोबाइल नंबर को प्राइवेट नंबर बनाने के लिए तरीका (4)

आपको पहले GetStringData को MyAsyncMethod विधि बनाने पर विचार करना चाहिए और यह MyAsyncMethod से MyAsyncMethod गए कार्य का await कर MyAsyncMethod

यदि आप पूरी तरह से सुनिश्चित हैं कि आपको MyAsyncMethod से अपवादों को संभालने की आवश्यकता नहीं है या यह पूरा होने पर पता है, तो आप यह कर सकते हैं:

public string GetStringData()
{
  var _ = MyAsyncMethod();
  return "hello world";
}

बीटीडब्ल्यू, यह एक "आम समस्या" नहीं है। कुछ कोड निष्पादित करना बहुत दुर्लभ है और यह परवाह नहीं है कि यह पूरा हो गया है या नहीं, परवाह है कि यह सफलतापूर्वक पूरा हो गया है या नहीं।

अद्यतन करें:

चूंकि आप एएसपी.नेट पर हैं और जल्दी लौटने की इच्छा रखते हैं, तो आप विषय पर मेरे ब्लॉग पोस्ट को उपयोगी पा सकते हैं। हालांकि, एएसपी.नेट को इसके लिए डिज़ाइन नहीं किया गया था, और इस बात की कोई गारंटी नहीं है कि प्रतिक्रिया वापस आने के बाद आपका कोड चलाएगा। एएसपी.नेट इसे चलाने के लिए अपनी पूरी कोशिश करेगा, लेकिन यह इसकी गारंटी नहीं दे सकता है।

तो, यह किसी घटना को एक लॉग में फेंकने जैसी सरल चीज़ के लिए एक अच्छा समाधान है, जहां वास्तव में कोई फर्क नहीं पड़ता कि आप यहां कुछ और खो देते हैं। यह किसी भी तरह के व्यापार-महत्वपूर्ण संचालन के लिए एक अच्छा समाधान नहीं है। उन परिस्थितियों में, आपको संचालन को बचाने के लिए एक सतत तरीका (उदाहरण के लिए, Azure Queues, MSMQ) और एक अलग पृष्ठभूमि प्रक्रिया (उदाहरण के लिए, Azure वर्कर रोल, Win32 सेवा) को संसाधित करने के लिए एक और जटिल आर्किटेक्चर को अपनाना होगा

मेरे पास एक async विधि है जो कोई डेटा नहीं देती है:

public async Task MyAsyncMethod()
{
    // do some stuff async, don't return any data
}

मैं इसे किसी अन्य विधि से बुला रहा हूं जो कुछ डेटा देता है:

public string GetStringData()
{
    MyAsyncMethod(); // this generates a warning and swallows exceptions
    return "hello world";
}

बिना प्रतीक्षा किए MyAsyncMethod() को कॉल करने से " चूंकि इस कॉल की प्रतीक्षा नहीं की जा रही है, इसलिए दृश्य स्टूडियो में चेतावनी समाप्त होने से पहले मौजूदा विधि चलाना जारी है "। उस चेतावनी के लिए पृष्ठ पर यह कहता है:

आपको चेतावनी को दबाने पर विचार करना चाहिए यदि आप सुनिश्चित हैं कि आप एसिंक्रोनस कॉल को पूरा करने के लिए इंतजार नहीं करना चाहते हैं और कहा जाता है कि बुलाया गया कोई अपवाद नहीं उठाएगा

मुझे यकीन है कि मैं कॉल को पूरा करने के लिए इंतजार नहीं करना चाहता; मुझे समय की आवश्यकता नहीं है या नहीं। लेकिन कॉल अपवाद उठा सकता है।

मैंने इस समस्या में कुछ बार ठोकर खाई है और मुझे यकीन है कि यह एक आम समस्या है जिसमें एक सामान्य समाधान होना चाहिए।

मैं परिणाम की प्रतीक्षा किए बिना एसिंक विधि को सुरक्षित रूप से कैसे कॉल करूं?

अद्यतन करें:

लोगों के सुझाव के लिए कि मैं केवल परिणाम का इंतजार कर रहा हूं, यह वह कोड है जो हमारी वेब सेवा (एएसपी.नेट वेब एपीआई) पर वेब अनुरोध का जवाब दे रहा है। यूआई संदर्भ में प्रतीक्षा करने से यूआई थ्रेड मुक्त रहता है, लेकिन वेब अनुरोध कॉल में प्रतीक्षा करने से अनुरोध का जवाब देने से पहले कार्य समाप्त होने की प्रतीक्षा होगी, जिससे कोई कारण नहीं होने पर प्रतिक्रिया समय बढ़ जाएगा।


पीटर रिची का जवाब वह था जो मैं चाहता था, और एएसपी.NET में जल्दी लौटने के बारे में स्टीफन क्लेरी का लेख बहुत उपयोगी था।

हालांकि एक सामान्य समस्या के रूप में (एएसपी.NET संदर्भ के लिए विशिष्ट नहीं) निम्नलिखित कंसोल एप्लिकेशन कार्य का उपयोग कर पीटर के उत्तर के उपयोग और व्यवहार को दर्शाता है। Task.ContinueWith(...)

static void Main(string[] args)
{
  try
  {
    // output "hello world" as method returns early
    Console.WriteLine(GetStringData());
  }
  catch
  {
    // Exception is NOT caught here
  }
  Console.ReadLine();
}

public static string GetStringData()
{
  MyAsyncMethod().ContinueWith(OnMyAsyncMethodFailed, TaskContinuationOptions.OnlyOnFaulted);
  return "hello world";
}

public static async Task MyAsyncMethod()
{
  await Task.Run(() => { throw new Exception("thrown on background thread"); });
}

public static void OnMyAsyncMethodFailed(Task task)
{
  Exception ex = task.Exception;
  // Deal with exceptions here however you want
}

GetStringData() MyAsyncMethod() इंतजार किए बिना जल्दी लौटता है और MyAsyncMethod() में MyAsyncMethod() अपवादों को OnMyAsyncMethodFailed(Task task) में निपटाया जाता है और GetStringData() आसपास try / catch में नहीं किया जाता है


मैं इस समाधान के साथ समाप्त होता है:

public async Task MyAsyncMethod()
{
    // do some stuff async, don't return any data
}

public string GetStringData()
{
    // Run async, no warning, exception are catched
    RunAsync(MyAsyncMethod()); 
    return "hello world";
}

private void RunAsync(Task task)
{
    task.ContinueWith(t =>
    {
        ILog log = ServiceLocator.Current.GetInstance<ILog>();
        log.Error("Unexpected Error", t.Exception);

    }, TaskContinuationOptions.OnlyOnFaulted);
}

यदि आप अपवाद "असीमित रूप से" प्राप्त करना चाहते हैं, तो आप यह कर सकते हैं:

  MyAsyncMethod().
    ContinueWith(t => Console.WriteLine(t.Exception),
        TaskContinuationOptions.OnlyOnFaulted);

यह आपको "मुख्य" थ्रेड के अलावा किसी थ्रेड पर अपवाद से निपटने की अनुमति देगा। इसका अर्थ यह है कि आपको MyAsyncMethod() को कॉल के लिए "प्रतीक्षा" करने की आवश्यकता नहीं है जो MyAsyncMethod कॉल MyAsyncMethod ; लेकिन, अभी भी आपको अपवाद के साथ कुछ करने की अनुमति देता है - लेकिन केवल तभी अपवाद होता है।

अद्यतन करें:

तकनीकी रूप से, आप await साथ कुछ ऐसा कर सकते हैं:

try
{
    await MyAsyncMethod().ConfigureAwait(false);
}
catch (Exception ex)
{
    Trace.WriteLine(ex);
}

... जो उपयोगी होगा यदि आपको विशेष रूप से try / catch (या using ) using करने की आवश्यकता है, लेकिन मुझे लगता है कि ContinueWith लिए थोड़ा और स्पष्ट होना चाहिए क्योंकि आपको यह जानना है कि ConfigureAwait(false) अर्थ क्या है।






async-await