تفويض مهمة والحصول على إشعار عند اكتمالها (في C#)

StackOverflow https://stackoverflow.com/questions/74880

  •  09-06-2019
  •  | 
  •  

سؤال

من الناحية النظرية، أرغب في إنجاز ما يلي ولكني أواجه مشكلة في فهم كيفية ترميزه بشكل صحيح في لغة C#:


SomeMethod { // Member of AClass{}
    DoSomething;
    Start WorkerMethod() from BClass in another thread;
    DoSomethingElse;
}

بعد ذلك، عند اكتمال WorkerMethod()، قم بتشغيل هذا:


void SomeOtherMethod()  // Also member of AClass{}
{ ... }

هل يمكن لأي شخص أن يعطي مثالا على ذلك؟

هل كانت مفيدة؟

المحلول

ال تطبيقBackgroundWorker تمت إضافة فئة إلى .NET 2.0 لهذا الغرض بالضبط.

باختصار عليك القيام بما يلي:

BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += delegate { myBClass.DoHardWork(); }
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(SomeOtherMethod);
worker.RunWorkerAsync();

يمكنك أيضًا إضافة أشياء رائعة مثل الإلغاء وإعداد التقارير المرحلية إذا كنت تريد ذلك :)

نصائح أخرى

في .Net 2، تم تقديم تطبيقBackgroundWorker، مما يجعل تشغيل العمليات غير المتزامنة أمرًا سهلاً للغاية:

BackgroundWorker bw = new BackgroundWorker { WorkerReportsProgress = true };

bw.DoWork += (sender, e) => 
   {
       //what happens here must not touch the form
       //as it's in a different thread
   };

bw.ProgressChanged += ( sender, e ) =>
   {
       //update progress bars here
   };

bw.RunWorkerCompleted += (sender, e) => 
   {
       //now you're back in the UI thread you can update the form
       //remember to dispose of bw now
   };

worker.RunWorkerAsync();

في .Net 1 عليك استخدام المواضيع.

يجب عليك استخدام AsyncCallBacks.يمكنك استخدام AsyncCallBacks لتحديد مفوض لأسلوب ما، ثم تحديد أساليب CallBack التي يتم استدعاؤها بمجرد اكتمال تنفيذ الأسلوب الهدف.

إليك مثال صغير، قم بتشغيله وشاهده بنفسك.

برنامج الفصل {

    public delegate void AsyncMethodCaller();


    public static void WorkerMethod()
    {
        Console.WriteLine("I am the first method that is called.");
        Thread.Sleep(5000);
        Console.WriteLine("Exiting from WorkerMethod.");
    }

    public static void SomeOtherMethod(IAsyncResult result)
    {
        Console.WriteLine("I am called after the Worker Method completes.");
    }



    static void Main(string[] args)
    {
        AsyncMethodCaller asyncCaller = new AsyncMethodCaller(WorkerMethod);
        AsyncCallback callBack = new AsyncCallback(SomeOtherMethod);
        IAsyncResult result = asyncCaller.BeginInvoke(callBack, null);
        Console.WriteLine("Worker method has been called.");
        Console.WriteLine("Waiting for all invocations to complete.");
        Console.Read();

    }
}

على الرغم من وجود العديد من الاحتمالات هنا، إلا أنني سأستخدم مندوبًا، يُسمى بشكل غير متزامن باستخدام BeginInvoke طريقة.

تحذير :لا تنس الاتصال دائما EndInvoke على ال IAsyncResult لتجنب تسرب الذاكرة في نهاية المطاف، كما هو موضح في هذا المقال.

تحقق من عامل الخلفية.

استخدام المندوبين غير المتزامنين:

// Method that does the real work
public int SomeMethod(int someInput)
{
Thread.Sleep(20);
Console.WriteLine(”Processed input : {0}”,someInput);
return someInput+1;
} 


// Method that will be called after work is complete
public void EndSomeOtherMethod(IAsyncResult result)
{
SomeMethodDelegate myDelegate = result.AsyncState as SomeMethodDelegate;
// obtain the result
int resultVal = myDelegate.EndInvoke(result);
Console.WriteLine(”Returned output : {0}”,resultVal);
}

// Define a delegate
delegate int SomeMethodDelegate(int someInput);
SomeMethodDelegate someMethodDelegate = SomeMethod;

// Call the method that does the real work
// Give the method name that must be called once the work is completed.
someMethodDelegate.BeginInvoke(10, // Input parameter to SomeMethod()
EndSomeOtherMethod, // Callback Method
someMethodDelegate); // AsyncState

حسنًا، لست متأكدًا من الطريقة التي تريد بها القيام بهذا الأمر.من المثال الخاص بك، يبدو أن WorkerMethod لا يقوم بإنشاء مؤشر ترابط خاص به للتنفيذ ضمنه، ولكنك تريد استدعاء هذا الأسلوب على مؤشر ترابط آخر.

في هذه الحالة، قم بإنشاء أسلوب عامل قصير يستدعي WorkerMethod ثم يستدعي SomeOtherMethod، ويضع هذا الأسلوب في قائمة الانتظار على مؤشر ترابط آخر.ثم عند اكتمال WorkerMethod، يتم استدعاء SomeOtherMethod.على سبيل المثال:

public class AClass
{
    public void SomeMethod()
    {
        DoSomething();

        ThreadPool.QueueUserWorkItem(delegate(object state)
        {
            BClass.WorkerMethod();
            SomeOtherMethod();
        });

        DoSomethingElse();
    }

    private void SomeOtherMethod()
    {
        // handle the fact that WorkerMethod has completed. 
        // Note that this is called on the Worker Thread, not
        // the main thread.
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top