अनाम कॉल में अनाम विधि


131

सिंटैक्स के साथ थोड़ी परेशानी होना जहां हम एक प्रतिनिधि को एक कंट्रोल के भीतर गुमनाम रूप से कॉल करना चाहते हैं। इंवोक।

हमने कई अलग-अलग तरीकों की कोशिश की है, सभी का कोई फायदा नहीं हुआ है।

उदाहरण के लिए:

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

जहाँ someParameter इस विधि के लिए स्थानीय है

ऊपर एक संकलक त्रुटि में परिणाम होगा:

अनाम पद्धति को 'System.Delegate' टाइप करने के लिए परिवर्तित नहीं किया जा सकता क्योंकि यह एक प्रतिनिधि प्रकार नहीं है

जवाबों:


221

क्योंकि 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 = "हाय;}});
uzay95 14

1
एक्सटेंशन एक्शन के बिना एक्सप्लोसिव कास्ट किए बिना एक्सटेंशन मेथड क्यों मंगवाया जाता है?
पी। ब्रायन। मैके

क्योंकि संकलक उपयोग से अनुमान लगा सकता है।
रोबो जेएम 1

1
यह Form.Load += Loader()पुराने के बजाय ऐसा करने में सक्षम हैForm.Load += new EventHandler(Loader())
रोबो जेएम 1

49

वास्तव में आपको प्रतिनिधि कीवर्ड का उपयोग करने की आवश्यकता नहीं है। बस लैम्बडा को पैरामीटर के रूप में पास करें:

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


13

आपको एक प्रतिनिधि प्रकार बनाने की आवश्यकता है। अनाम विधि निर्माण में 'प्रतिनिधि' शब्द थोड़ा भ्रामक है। आप एक अनाम प्रतिनिधि नहीं बल्कि एक अनाम विधि बना रहे हैं। आपके द्वारा बनाई गई विधि का उपयोग किसी प्रतिनिधि में किया जा सकता है। ऐशे ही:

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

8

संपूर्णता के लिए, यह एक एक्शन विधि / अनाम विधि संयोजन के माध्यम से भी पूरा किया जा सकता है:

//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();
});

Invoke((Action) Process);सबसे अच्छा जवाब है, धन्यवाद!
जिनजिनोव

5

मुझे अन्य सुझावों के साथ समस्या थी क्योंकि मैं कभी-कभी अपने तरीकों से मूल्यों को वापस करना चाहता हूं। यदि आप वापसी मानों के साथ MethodInvoker का उपयोग करने का प्रयास करते हैं, तो यह पसंद नहीं है। तो मेरे द्वारा उपयोग किया जाने वाला समाधान इस तरह है (इस अधिक रसीला बनाने के तरीके को सुनकर बहुत खुशी हुई - मैं सी # .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;
        }));
    }

1

मुझे MethodInvoker के स्थान पर Action का उपयोग करना पसंद है, यह छोटा है और साफ दिखता है।

Invoke((Action)(() => {
    DoSomething();
}));

// OR

Invoke((Action)delegate {
    DoSomething();
});

उदाहरण के लिए।

// Thread-safe update on a form control
public void DisplayResult(string text){
    if (txtResult.InvokeRequired){
        txtResult.Invoke((Action)delegate {
            DisplayResult(text);
        });
        return;
    }

    txtResult.Text += text + "\r\n";
}

0

मुझे कभी समझ में नहीं आया कि यह संकलक के लिए क्यों फर्क पड़ता है, लेकिन यह पर्याप्त है।

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) { }
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.