c# - Invoke(Delegate)




winforms delegates (9)

هل يمكن لأي شخص أن يفسر هذا البيان المكتوب على هذا link

Invoke(Delegate):

تنفيذ المفوض المحدد على مؤشر الترابط الذي يملك مقبض الإطار الأساسي لعنصر التحكم.

هل يستطيع أحد أن يفسر ما يعنيه هذا (لا سيما الجريء) أنا غير قادر على الحصول عليه بوضوح


Answers

المندوب هي أساسا inline Action أو Func<T> . يمكنك الإعلان عن مندوب خارج نطاق الطريقة التي تقوم بتشغيلها أو باستخدام تعبير lambda ( => )؛ لأنك قمت بتشغيل المفوض داخل إحدى الطريقتين ، فأنت تقوم بتشغيله على مؤشر الترابط الذي يتم تشغيله للإطار / التطبيق الحالي الذي يكون بحجم البت الغامق.

لامدا سبيل المثال

int AddFiveToNumber(int number)
{
  var d = (int i => i + 5);
  d.Invoke(number);
}

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

النمط هو:

void OnEvent(object sender, EventArgs e)
{
   if (this.InvokeRequired)
   {
       this.Invoke(() => this.OnEvent(sender, e);
       return;
   }

   // do stuff (now you know you are on the main thread)
}

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

في أسفل مؤشر ترابط العينة 1 throws استثناء لأن SetText1 يحاول تعديل textBox1.Text من مؤشر ترابط آخر. ولكن في thread2 ، يتم تنفيذ الإجراء في SetText2 في مؤشر الترابط الذي تم إنشاؤه في TextBox

private void btn_Click(object sender, EvenetArgs e)
{
    var thread1 = new Thread(SetText1);
    var thread2 = new Thread(SetText2);
    thread1.Start();
    thread2.Start();
}

private void SetText1() 
{
    textBox1.Text = "Test";
}

private void SetText2() 
{
    textBox1.Invoke(new Action(() => textBox1.Text = "Test"));
}

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

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


this.Invoke(delegate) تأكد من أن تقوم باستدعاء المفوض الوسيطة لهذا. this.Invoke() على مؤشر الترابط الرئيسي / إنشاء مؤشر الترابط.

يمكنني القول أن قاعدة "الإبهام" لا يمكنها الوصول إلى عناصر التحكم في النموذج إلا من مؤشر الترابط الرئيسي.

قد تكون الأسطر التالية منطقية لاستخدام Invoke ()

    private void SetText(string text)
    {
        // InvokeRequired required compares the thread ID of the
        // calling thread to the thread ID of the creating thread.
        // If these threads are different, it returns true.
        if (this.textBox1.InvokeRequired)
        {   
            SetTextCallback d = new SetTextCallback(SetText);
            this.Invoke(d, new object[] { text });
        }
        else
        {
            this.textBox1.Text = text;
        }
    }

هناك حالات بالرغم من إنشاء مؤشر ترابط Threadpool (أي مؤشر ترابط عامل) سيتم تشغيله على مؤشر الترابط الرئيسي. لن يتم إنشاء مؤشر ترابط Coz مؤشر ترابط جديد يتوفر لمعالجة مزيد من الإرشادات. لذلك تحقق أولاً ما إذا كان مؤشر الترابط الحالي قيد this.InvokeRequired الرئيسي باستخدام هذا. this.InvokeRequired إذا ترجع true تشغيل التعليمة البرمجية الحالية على مؤشر ترابط worker لذلك استدعاء هذا. Invoke (d ، كائن جديد [] {text})؛

آخر تحديث عنصر واجهة المستخدم مباشرة (هنا يضمن لك تشغيل التعليمات البرمجية في مؤشر الترابط الرئيسي.)


عنصر تحكم أو كائن إطار في Windows Forms هو مجرد التفاف حول إطار Win32 المعرفة بواسطة مؤشر (تسمى أحياناً HWND). ستؤدي معظم الأشياء التي تقوم بها مع عنصر التحكم في نهاية المطاف إلى استدعاء Win32 API يستخدم هذا المؤشر. يمتلك المؤشر مؤشر الترابط الذي أنشأه (عادةً مؤشر الترابط الرئيسي) ولا يجب معالجته بواسطة مؤشر ترابط آخر. إذا كنت بحاجة إلى القيام بشيء ما مع عنصر التحكم من سلسلة رسائل أخرى ، فيمكنك استخدام Invoke لسؤال الموضوع الرئيسي للقيام بذلك نيابة عنك.

على سبيل المثال ، إذا كنت تريد تغيير نص تصنيف من ترابط عامل ، فيمكنك القيام بشيء كالتالي:

theLabel.Invoke(new Action(() => theLabel.Text = "hello world from worker thread!"));

تكمن الإجابة على هذا السؤال في كيفية عمل C # Controls

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

من msdn.microsoft.com/en-us/library/…

على نحو فعال ، ما تقوم به Invoke هو التأكد من أن الرمز الذي تتصل به يحدث على مؤشر الترابط الذي "يعمل" بشكل فعال يمنع الاستثناءات المترابطة عبر.

من منظور تاريخي ، في .Net 1.1 ، تم السماح بذلك بالفعل. ما يعنيه هو أنه يمكنك محاولة تنفيذ التعليمات البرمجية على مؤشر ترابط "واجهة المستخدم الرسومية" من أي مؤشر ترابط الخلفية وهذا من شأنه العمل في الغالب. في بعض الأحيان ، قد يؤدي ذلك إلى إنهاء تطبيقك نظرًا لأنك كنت تقطع فعليًا مؤشر ترابط واجهة المستخدم الرسومية بينما كانت تفعل شيئًا آخر. هذا هو استثناء الخيوط المتقاطعة - تخيل محاولة تحديث مربع نص بينما يقوم واجهة المستخدم الرسومية برسم شيء آخر.

  • ما هو الإجراء الذي يأخذ الأولوية؟
  • هل من الممكن أن يحدث كلاهما في وقت واحد؟
  • ما الذي يحدث لجميع الأوامر الأخرى التي تحتاج إليها واجهة المستخدم الرسومية؟

على نحو فعال ، أنت تفرغ قائمة انتظار ، والتي يمكن أن يكون لها الكثير من النتائج غير المتوقعة. Invoke هو طريقة "مهذبة" بشكل فعال للحصول على ما تريد القيام به في قائمة الانتظار هذه ، وتم فرض هذه القاعدة من .Net 2.0 فصاعدا عبر InvalidOperationException .

لفهم ما يجري في الواقع وراء الكواليس ، وما هو المقصود بـ "واجهة المستخدم الرسومية" ، من المفيد أن نفهم ما هي رسالة مضخة أو رسالة حلقة.

لقد تمت الإجابة بالفعل على هذا السؤال في السؤال " ما هي مضخة الرسائل " وأوصت بقراءة لفهم الآلية الفعلية التي ترتبط بها عند التفاعل مع عناصر التحكم.

القراءة الأخرى التي قد تجدها مفيدة تشمل:

ما الأمر مع Begin Invoke

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

وللحصول على نظرة عامة على التعليمات البرمجية بشكل كبير مع عينة تمثيلية:

عمليات مؤشر الترابط غير صالح

// the canonical form (C# consumer)

public delegate void ControlStringConsumer(Control control, string text);  // defines a delegate type

public void SetText(Control control, string text) {
    if (control.InvokeRequired) {
        control.Invoke(new ControlStringConsumer(SetText), new object[]{control, text});  // invoking itself
    } else {
        control.Text=text;      // the "functional part", executing only on the main thread
    }
}

بمجرد الحصول على تقدير لـ InvokeRequired ، قد ترغب في التفكير في استخدام طريقة ملحق لملء هذه المكالمات. هذا هو ably تغطيتها في مسألة تجاوز المكدس تنظيف التعليمات البرمجية تناثرت مع Invoke المطلوبة .

هناك أيضا كتابات أخرى حول ما حدث تاريخيا والتي قد تكون ذات فائدة.


هذا يعني أنه يتم تنفيذ المفوض الذي تقوم بتمريره على مؤشر الترابط الذي أنشأ كائن التحكم (وهو مؤشر ترابط واجهة المستخدم).

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


هناك طريقة TryParse ، والتي تُرجع TryParse يشير إلى ما إذا كان التحويل ناجحًا.







c# winforms delegates invoke