[c#] async / await - متى يتم إرجاع مهمة مقابل void؟



Answers

لقد صادفت هذه المقالة async حول async التي كتبها جيروم لابان: http://www.jaylee.org/post/2012/07/08/c-sharp-async-tips-and-tricks-part-2-async-void.aspx

خلاصة القول هي أن async+void يمكن أن يتلف النظام ، وعادةً ما يجب استخدامه فقط في معالجات الأحداث الجانبية لواجهة المستخدم.

السبب وراء هذا هو سياق التزامن المستخدم من قبل AsyncVoidMethodBuilder ، حيث لا يوجد في هذا المثال. عندما لا يكون هناك سياق التزامن المحيط ، أي استثناء غير معالَج من قبل جسم طريقة عدم التزاق غير متصل على ThreadPool. على الرغم من أنه لا يوجد أي مكان منطقي آخر حيث يمكن طرح هذا النوع من الاستثناءات غير المعالجة ، فإن التأثير المؤسف هو إنهاء العملية ، لأن الاستثناءات غير المعالجة على ThreadPool تنهي العملية بفعالية منذ .NET 2.0. يمكنك اعتراض كافة الاستثناءات غير المعالجة باستخدام الحدث AppDomain.UnhandledException ، ولكن لا توجد طريقة لاسترداد العملية من هذا الحدث.

عند كتابة معالجات أحداث واجهة المستخدم ، تكون طرق الفراغ المتزامن غير مؤلمة إلى حدٍّ ما لأن الاستثناءات تُعامل بالطريقة نفسها الموجودة في الطرق غير المتزامنة ؛ يتم طرحها على المرسل. هناك إمكانية للتعافي من مثل هذه الاستثناءات ، مع أكثر من الصحيح لمعظم الحالات. خارج معالجات الأحداث في واجهة المستخدم ومع ذلك ، فإن أساليب الفراغ المتزامن هي بطريقة ما خطرة في الاستخدام وربما لا يسهل العثور عليها.

Question

تحت أي سيناريوهات يريد المرء استخدامها

public async Task AsyncMethod(int num)

بدلا من

public async void AsyncMethod(int num)

السيناريو الوحيد الذي يمكنني التفكير فيه هو إذا كنت بحاجة إلى مهمة لتكون قادرة على تتبع تقدمها.

بالإضافة إلى ذلك ، في الطريقة التالية ، هل تعد الكلمات المتزامنة وتنتظر غير ضرورية؟

  public static async void AsyncMethod2(int num)
    {
        await Task.Factory.StartNew(() => Thread.Sleep(num));
    }



أعتقد أنه يمكنك استخدام async void أجل تشغيل عمليات الخلفية أيضًا ، طالما أنك تحرص على الإمساك بالاستثناءات. أفكار؟

class Program {

    static bool isFinished = false;

    static void Main(string[] args) {

        // Kick off the background operation and don't care about when it completes
        BackgroundWork();

        Console.WriteLine("Press enter when you're ready to stop the background operation.");
        Console.ReadLine();
        isFinished = true;
    }

    // Using async void to kickoff a background operation that nobody wants to be notified about when it completes.
    static async void BackgroundWork() {
        // It's important to catch exceptions so we don't crash the appliation.
        try {
            // This operation will end after ten interations or when the app closes. Whichever happens first.
            for (var count = 1; count <= 10 && !isFinished; count++) {
                await Task.Delay(1000);
                Console.WriteLine($"{count} seconds of work elapsed.");
            }
            Console.WriteLine("Background operation came to an end.");
        } catch (Exception x) {
            Console.WriteLine("Caught exception:");
            Console.WriteLine(x.ToString());
        }
    }
}



Related