كيفية استدعاء أسلوب Visual C# بشكل غير متزامن

ملخص

يسهل Microsoft.NET Framework لاستدعاء دالات بشكل غير متزامن. استدعاء الدالات بشكل غير متزامن يؤدي النظام لتنفيذها في الخلفية على مؤشر ترابط ثانوي بينما يستمر استدعاء الدالة للقيام بعمل آخر. في استدعاء دالة نموذجي (متزامن)، يتم تنفيذ الدالة مباشرة على نفس مؤشر الترابط الذي وجه هذه الدعوة. انتظار المكالمة لإكمال استدعاء دالة ويتلقى نتائج الاتصال قبل المتابعة. وفي المقابل، عند إجراء استدعاء غير متزامن، استرداد نتائج استدعاء متزامن لاحقاً. توضح هذه المقالة كيفية القيام بذلك باستخدام Visual C#.

متطلبات


توضح القائمة التالية الأجهزة الموصى بها برامج البنية الأساسية للشبكة وحزم الخدمات المطلوبة:
  • نظام التشغيل Microsoft Windows 2000 أو نظام التشغيل Microsoft Windows XP أو نظام التشغيل Microsoft Windows Server 2003
  • Visual Studio.NET أو Visual Studio 2005
تفترض هذه المقالة أنك معتاد على المواضيع التالية:
  • استدعاء الأساليب في Visual C#
  • كيفية استخدام التفويضات

كيفية إجراء استدعاءات غير متزامن

يتم إجراء استدعاءات غير متزامن باستخدام التفويضات. مفوض هو كائن التفاف دالة. المفوضين توفير دالة متزامن وأيضا توفر أساليب لاستدعاء الدالة الملتفة بشكل غير متزامن. هذه الأساليب هي BeginInvoke() و EndInvoke(). قوائم المعلمات لهذه الأساليب تختلف توقيع الدالة التي يلتف المفوض. لاحظ أن الميزة Visual Studio.NET التحسس الذكي لا تعرض BeginInvoke() و EndInvoke()، حيث لم تر جعلها تظهر في القوائم الدالة أثناء الكتابة.


يتم استخدام BeginInvoke() لبدء الاتصال غير متزامن. يكون له نفس المعلمات الملتفة دالة، بالإضافة إلى معلمتين من معلمات إضافية التي سيتم وصفها لاحقاً في هذا المقال. BeginInvoke() إرجاع مباشرة ولا ينتظر إكمال الاستدعاء غير متزامن. BeginInvoke() إرجاع كائن IAsyncResult .

يتم استخدام الدالة EndInvoke() لاسترداد نتائج الاستدعاء غير متزامن. يمكن استدعاؤها في أي وقت بعد BeginInvoke(). في حالة استدعاء متزامن لم تستكمل بعد، EndInvoke() كتل حتى يكتمل. يتضمن معلمات الدالة EndInvoke() بها و
معلمات المرجع يحتوي على الدالة الملتفة، بالإضافة إلى كائن IAsyncResult التي تم إرجاعها بواسطة BeginInvoke().

ما يلي مثال مفوض وأساليب BeginInvoke() و EndInvoke() :
// The following delegate delegate string MethodDelegate(int iCallTime, out int iExecThread)  ;

// will have the following BeginInvoke() and EndInvoke methods:
IAsyncResult MethodDelegate.BeginInvoke(int iCallTime, out int iExecThread, AsyncCallback cb, object AsyncState);

string MethodDelegate.EndInvoke (out int iExecThread, IAsyncResult ar) ;

هناك أربع طرق الشائعة لاستخدام BeginInvoke() و EndInvoke() لإجراء استدعاءات غير متزامن. بعد استدعاء BeginInvoke()، يمكنك:
  • بشكل اختياري القيام ببعض الأعمال واستخدم EndInvoke().
  • الحصول على WaitHandle يتم توفيرها من قبل كائن IAsyncResult واستخدم أسلوب ويتون لحظر حتى يتم الإشارة WaitHandle ثم استدعاء EndInvoke().
  • استقصاء كائن IAsyncResult تحديد متى تم إكمال استدعاء متزامن، ثم قم باستدعاء EndInvoke().
  • يكون نظام استدعاء دالة رد اتصال الذي قمت بتحديده. دالة رد الاتصال هذا يستدعي EndInvoke() ومعالجة نتائج استدعاء متزامن عند اكتماله.
نماذج التعليمات البرمجية التالية توضح هذه الكلمة النقوش وعلى إجراء استدعاء متزامن باستخدام الدالة التالية خلاف:
string LongRunningMethod (int iCallTime, out int iExecThread){
Thread.Sleep (iCallTime) ;
iExecThread = AppDomain.GetCurrentThreadId ();
return "MyCallTime was " + iCallTime.ToString() ;
}


يحاكي LongRunningMethod() دالة التي يتم تشغيلها لفترة طويلة من النوم. تقوم بإرجاع معرف مؤشر الترابط الذي يقوم بالتنفيذ ووقت السكون. إذا قمت بالاتصال بشكل غير متزامن، تجد أن معرف مؤشر الترابط لتنفيذ مؤشر ترابط مختلف من مؤشر ترابط استدعاء.

الخطوة الأولى هي تعريف المفوض الذي يلتف الدالة:
delegate string MethodDelegate(int iCallTime, out int iExecThread)  ;

النموذج الأول: استدعاء أسلوب شكل متزامن

يوضح هذا النموذج كيفية الاتصال LongRunningMethod() بشكل متزامن باستخدام تفويض ميثوديليجاتي . نماذج أخرى خلاف ذلك بإجراء مكالمات بشكل غير متزامن.
  1. بدء تشغيل Microsoft Visual Studio.NET أو Microsoft Visual Studio 2005.
  2. إنشاء مشروع تطبيق Visual C# وحدة تحكم جديد باسم أسينكديمو.
  3. إضافة فئة بالاسم أسينكديمو الذي تم تحديده كالتالي للمشروع في ملف.cs جديد:
    using System;using System.Threading ; 
    using System.Windows.Forms ;

    public class AsyncDemo
    {
    string LongRunningMethod (int iCallTime, out int iExecThread)
    {
    Thread.Sleep (iCallTime) ;
    iExecThread = AppDomain.GetCurrentThreadId ();
    return "MyCallTime was " + iCallTime.ToString() ;
    }

    delegate string MethodDelegate(int iCallTime, out int iExecThread) ;

    public void DemoSyncCall()
    {
    string s ;
    int iExecThread;

    // Create an instance of a delegate that wraps LongRunningMethod.
    MethodDelegate dlgt = new MethodDelegate (this.LongRunningMethod) ;

    // Call LongRunningMethod using the delegate.
    s = dlgt(3000, out iExecThread);

    MessageBox.Show (string.Format ("The delegate call returned the string: \"{0}\",
    and the thread ID {1}", s, iExecThread.ToString() ) );
    }
    }

    وبعد هذه الفئة يوضح كيفية إجراء استدعاءات غير متزامن. وفي البداية، ولكنه فقط يحتوي على الأسلوب DemoSyncCall() ، الذي يوضح كيفية استدعاء المفوض شكل متزامن.
  4. أضف التعليمات البرمجية التالية في نص الدالة الرئيسي يقوم Visual Studio تلقائياً في المشروع الخاص بك:
    static void Main(string[] args){
    AsyncDemo ad = new AsyncDemo () ;
    ad.DemoSyncCall() ;
    }

  5. اضغط CTRL + F5 لتشغيل التطبيق الخاص بك.

النموذج 2: استدعاء أسلوب بشكل غير متزامن باستخدام نمط استدعاء EndInvoke()

في هذا القسم، يستدعي العينة نفس الأسلوب بشكل غير متزامن. نمط الاتصال الذي يتم استخدامه لاستدعاء BeginInvoke، القيام ببعض العمل على مؤشر الترابط الرئيسي، ثم قم باستدعاء EndInvoke(). لاحظ أن EndInvoke() لا يرجع حتى يكتمل الاستدعاء غير متزامن. نموذج استدعاء هذا مفيد عندما تريد أن يكون مؤشر ترابط استدعاء العمل في نفس الوقت تنفيذ الاستدعاء غير متزامن. يمكن وجود العمل التي تحدث في نفس الوقت إلى تحسين أداء العديد من التطبيقات. المهام الشائعة لتشغيل بشكل غير متزامن بهذه الطريقة تكون عمليات الملف أو شبكة الاتصال.
  1. إضافة أسلوب يسمى DemoEndInvoke() إلى فئة أسينكديمو . ديموندينفوكي الدالة توضح كيفية استدعاء المفوض بشكل غير متزامن.
    public void DemoEndInvoke(){
    MethodDelegate dlgt = new MethodDelegate (this.LongRunningMethod) ;
    string s ;
    int iExecThread;

    // Initiate the asynchronous call.
    IAsyncResult ar = dlgt.BeginInvoke(3000, out iExecThread, null, null);

    // Do some useful work here. This would be work you want to have
    // run at the same time as the asynchronous call.

    // Retrieve the results of the asynchronous call.
    s = dlgt.EndInvoke (out iExecThread, ar) ;

    MessageBox.Show (string.Format ("The delegate call returned the string: \"{0}\",
    and the number {1}", s, iExecThread.ToString() ) );
    }

  2. تحرير التعليمات البرمجية المصدر لالرئيسي حيث يحتوي على التعليمات البرمجية التالية:
    static void Main(string[] args){
    AsyncDemo ad = new AsyncDemo () ;
    ad.DemoEndInvoke() ;
    }

  3. اضغط CTRL + F5 لتشغيل التطبيق الخاص بك.

النموذج 3: استدعاء أسلوب بشكل غير متزامن واستخدام WaitHandle لانتظار المكالمة لإكمال


في هذا المقطع العينة استدعاء الأسلوب بشكل غير متزامن وينتظر WaitHandle قبل أن يستدعي EndInvoke(). لقد IAsyncResult التي تم إرجاعها بواسطة BeginInvoke() خاصية أسينكوايثاندلي . هذه الخاصية بإرجاع WaitHandle يتم الإشارة عند إكمال الاستدعاء غير متزامن. انتظار WaitHandle أسلوب مزامنة مؤشر ترابط شائعة. في انتظار مؤشر ترابط استدعاء على WaitHandle باستخدام أسلوب WaitOne() WaitHandle. كتل WaitOne() حتى يتم الإشارة WaitHandle . عندما يعود WaitOne() ، يمكن أن تقوم ببعض الأعمال الإضافية قبل استدعاء EndInvoke(). كما هو الحال في النموذج السابق، يعتبر هذا الأسلوب مفيداً لتنفيذ عمليات الملف أو شبكة الاتصال إلا حظر مؤشر ترابط الاتصال الرئيسي.
  1. إضافة دالة تسمى DemoWaitHandle() إلى فئة أسينكديمو . DemoWaitHandle() الدالة توضح كيفية استدعاء المفوض بشكل غير متزامن.
    public void DemoWaitHandle (){
    string s ;
    int iExecThread;

    MethodDelegate dlgt = new MethodDelegate (this.LongRunningMethod) ;

    // Initiate the asynchronous call.
    IAsyncResult ar = dlgt.BeginInvoke(3000, out iExecThread, null, null);

    // Do some useful work here. This would be work you want to have
    // run at the same time as the asynchronous call.

    // Wait for the WaitHandle to become signaled.
    ar.AsyncWaitHandle.WaitOne() ;

    // Get the results of the asynchronous call.
    s = dlgt.EndInvoke (out iExecThread, ar) ;

    MessageBox.Show (string.Format ("The delegate call returned the string: \"{0}\",
    and the number {1}", s, iExecThread.ToString() ) );
    }

  2. تحرير التعليمات البرمجية المصدر لالرئيسي حيث يحتوي على التعليمات البرمجية التالية:
    static void Main(string[] args){
    AsyncDemo ad = new AsyncDemo () ;
    ad.DemoWaitHandle () ;
    }

  3. اضغط CTRL + F5 لتشغيل التطبيق الخاص بك.

نموذج 4: استدعاء أسلوب بشكل غير متزامن باستخدام نمط الاتصال الاستقصاء

في هذا المقطع العينة يستقصي كائن IAsyncResult معرفة ما إذا تم إكمال الاستدعاء غير متزامن. يحتوي كائن IAsyncResult التي تم إرجاعها بواسطة BeginInvoke() خاصية إيسكومبليتيد إرجاع True بعد إكمال الاستدعاء غير متزامن. ثم يمكنك استدعاء EndInvoke(). يفيد هذا النمط الاتصال إذا كان التطبيق الخاص بك بالعمل المستمر الذي لا تريد قد حظره بواسطة استدعاء دالة تشغيلها لفترة طويلة. تطبيق Microsoft Windows مثالاً لذلك. متابعة مؤشر الترابط الرئيسي من تطبيق Windows معالجة إدخال المستخدم أثناء تنفيذ استدعاء غير متزامن. يمكنه بشكل دوري مراجعة IsCompleted لمعرفة إذا كان إتمام المكالمة. يقوم باستدعاء EndInvoke عندما تقوم إيسكومبليتيد بإرجاع True. لأن يمنع EndInvoke() حتى يتم اكتمال العملية غير المتزامنة، التطبيق لا يطلق عليه حتى أنه يعرف أن تكتمل العملية.
  1. إضافة دالة تسمى DemoPolling() إلى فئة أسينكديمو . الدالة DemoPolling() يوضح كيفية استدعاء المفوض بشكل غير متزامن واستخدام استقصاء لمعرفة ما إذا كانت العملية كاملة.
    public void DemoPolling(){
    MethodDelegate dlgt = new MethodDelegate (this.LongRunningMethod) ;
    string s ;
    int iExecThread;

    // Initiate the asynchronous call.
    IAsyncResult ar = dlgt.BeginInvoke(3000, out iExecThread, null, null);

    // Poll IAsyncResult.IsCompleted
    while(ar.IsCompleted == false)
    {
    Thread.Sleep (10) ; // pretend to so some useful work
    }
    s = dlgt.EndInvoke (out iExecThread, ar) ;

    MessageBox.Show (string.Format ("The delegate call returned the string: \"{0}\",
    and the number {1}", s, iExecThread.ToString() ) );
    }


  2. تحرير التعليمات البرمجية المصدر الرئيسي. استبدال المحتوى وظيفة بالتعليمات البرمجية التالية:
    static void Main(string[] args){
    AsyncDemo ad = new AsyncDemo () ;
    ad.DemoPolling () ;
    }

  3. اضغط CTRL + F5 لتشغيل التطبيق الخاص بك.

نموذج 5: تنفيذ رد اتصال عند اكتمال أسلوب غير متزامن

في هذا القسم، يوفر النموذج مفوض استدعاء للدالة BeginInvoke() تنفيذ النظام عند اكتمال الاستدعاء غير المتزامن. رد الاتصال يستدعي EndInvoke() ومعالجة نتائج الاستدعاء غير متزامن. يفيد هذا النمط الاتصال إذا كان مؤشر الترابط يقوم بتنفيذ الاستدعاء غير متزامن لا تحتاج إلى معالجة نتائج الاستدعاء. استدعاء النظام رد الاتصال على مؤشر ترابط خلاف بدء مؤشر الترابط عند إكمال الاستدعاء غير متزامن.


لاستخدام نمط الاتصال هذه، يجب أن تجتاز وض نوع أسينككالباك المعلمة الثانية والأخيرة للدالة BeginInvoke() . وقد BeginInvoke() أيضا معلمة الأخيرة لنوع الكائن الذي يمكنك تمرير أي كائن. يتوفر هذا الكائن إلى وظيفة رد الاتصال الخاصة بك عندما يتم استدعائه. أحد استخدامات هامة لهذه المعلمة هو تمرير التفويض الذي يستخدم لإجراء المكالمة. دالة رد الاتصال ثم استخدام الدالة EndInvoke() من التفويض لإتمام هذه المكالمة. ويظهر هذا النمط الاتصال أدناه.
  1. قم بإضافة أسلوبين المسماة DemoCallback() و MyAsyncCallback() للفئة أسينكديمو . أسلوب DemoCallback() يوضح كيفية استدعاء المفوض بشكل غير متزامن. يستخدم تفويض للالتفاف حول أسلوب MyAsyncCallback() ، الذي يستدعي النظام عند اكتمال العملية غير المتزامنة. استدعاء MyAsyncCallback() EndInvoke().
    public void DemoCallback(){
    MethodDelegate dlgt = new MethodDelegate (this.LongRunningMethod) ;
    string s ;
    int iExecThread;

    // Create the callback delegate.
    AsyncCallback cb = new AsyncCallback(MyAsyncCallback);

    // Initiate the Asynchronous call passing in the callback delegate
    // and the delegate object used to initiate the call.
    IAsyncResult ar = dlgt.BeginInvoke(3000, out iExecThread, cb, dlgt);
    }

    public void MyAsyncCallback(IAsyncResult ar)
    {
    string s ;
    int iExecThread ;

    // Because you passed your original delegate in the asyncState parameter
    // of the Begin call, you can get it back here to complete the call.
    MethodDelegate dlgt = (MethodDelegate) ar.AsyncState;

    // Complete the call.
    s = dlgt.EndInvoke (out iExecThread, ar) ;

    MessageBox.Show (string.Format ("The delegate call returned the string: \"{0}\",
    and the number {1}", s, iExecThread.ToString() ) );
    }


  2. تحرير التعليمات البرمجية المصدر الرئيسي. استبدال المحتوى وظيفة بالتعليمات البرمجية التالية:
    static void Main(string[] args){
    AsyncDemo ad = new AsyncDemo () ;
    ad.DemoCallback() ;
    }

  3. اضغط CTRL + F5 لتشغيل التطبيق الخاص بك.
خصائص

رقم الموضوع: 315582 - آخر مراجعة: 19‏/01‏/2017 - المراجعة: 1

تعليقات