سؤال

وبعد أن قليلا من المتاعب مع بناء الجملة حيث نريد لاستدعاء مندوب مجهول داخل Control.Invoke.

ولقد حاول عدد من المناهج المختلفة، ولكن دون جدوى.

وعلى سبيل المثال:

myControl.Invoke(delegate() { MyMethod(this, new MyEventArgs(someParameter)); }); 

وحيث someParameter غير المحلية إلى هذا الأسلوب

ما سبق سوف يؤدي إلى خطأ المترجم:

<اقتباس فقرة>   

لا يمكن تحويل طريقة المجهول إلى نوع 'System.Delegate' لأنه ليس نوع مندوب

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

المحلول

ولأن Invoke / BeginInvoke يقبل Delegate (بدلا من مندوب كتبته)، تحتاج لنقول للمترجم ما هو نوع من مندوب لخلق. MethodInvoker (2.0) أو Action (3.5) هي الخيارات المشتركة (لاحظ لديهم نفس التوقيع)؛ مثل ذلك:

control.Invoke((MethodInvoker) delegate {this.Text = "Hi";});

إذا كنت بحاجة إلى تمرير في المعلمات، "المتغيرات القبض على" ثم هي الطريقة:

string message = "Hi";
control.Invoke((MethodInvoker) delegate {this.Text = message;});

و(تحذير: عليك أن تكون حذرا بعض الشيء في حالة استخدام يلتقط <م> المتزامن ، لكن المزامنة على ما يرام - أي ما سبق على ما يرام)

وثمة خيار آخر هو لكتابة طريقة التمديد:

public static void Invoke(this Control control, Action action)
{
    control.Invoke((Delegate)action);
}

وبعد ذلك:

this.Invoke(delegate { this.Text = "hi"; });
// or since we are using C# 3.0
this.Invoke(() => { this.Text = "hi"; });

ويمكنك بالطبع أن تفعل الشيء نفسه مع BeginInvoke:

public static void BeginInvoke(this Control control, Action action)
{
    control.BeginInvoke((Delegate)action);
}

إذا لا يمكنك استخدام C # 3.0، هل يمكن أن تفعل الشيء نفسه مع أسلوب مثيل منتظم، ويفترض في Form قاعدة الطبقة.

نصائح أخرى

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

control.Invoke((MethodInvoker)(() => {this.Text = "Hi"; }));
myControl.Invoke(new MethodInvoker(delegate() {...}))

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

myControl.Invoke(new MethodInvoker(delegate() { (MyMethod(this, new MyEventArgs(someParameter)); }));

لمن أجل اكتمال، وهذا يمكن أيضا أن يتحقق عبر / الجمع بين طريقة مجهول طريقة العمل:

//Process is a method, invoked as a method group
Dispatcher.Current.BeginInvoke((Action) Process);
//or use an anonymous method
Dispatcher.Current.BeginInvoke((Action)delegate => {
  SomeFunc();
  SomeOtherFunc();
});

وكان لي مشاكل مع اقتراحات أخرى لأنني أريد أن يعود في بعض الأحيان القيم من أساليبي. إذا حاولت استخدام MethodInvoker مع القيم المرجعة لا يبدو أن مثل ذلك. وبالتالي فإن الحل الأول هو استخدام مثل هذا (سعيد جدا لسماع وسيلة لجعل هذا أكثر اقتضابا - أنا باستخدام C # .NET 2.0):

    // Create delegates for the different return types needed.
    private delegate void VoidDelegate();
    private delegate Boolean ReturnBooleanDelegate();
    private delegate Hashtable ReturnHashtableDelegate();

    // Now use the delegates and the delegate() keyword to create 
    // an anonymous method as required

    // Here a case where there's no value returned:
    public void SetTitle(string title)
    {
        myWindow.Invoke(new VoidDelegate(delegate()
        {
            myWindow.Text = title;
        }));
    }

    // Here's an example of a value being returned
    public Hashtable CurrentlyLoadedDocs()
    {
        return (Hashtable)myWindow.Invoke(new ReturnHashtableDelegate(delegate()
        {
            return myWindow.CurrentlyLoadedDocs;
        }));
    }

وأنا لم يفهم لماذا هذا يحدث فرقا للمترجم، ولكن هذا غير كاف.

public static class ControlExtensions
{
    public static void Invoke(this Control control, Action action)
    {
        control.Invoke(action);
    }
}

والمكافأة: إضافة بعض معالجة الأخطاء، لأنه من المحتمل أنه إذا كنت تستخدم Control.Invoke من ترابط خلفية تقوم بتحديث النص / التقدم / الدولة مكن من السيطرة ولا يهمني إذا تم التخلص من السيطرة بالفعل.

public static class ControlExtensions
{
    public static void Invoke(this Control control, Action action)
    {
        try
        {
            if (!control.IsDisposed) control.Invoke(action);
        }
        catch (ObjectDisposedException) { }
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top