簡體   English   中英

Invoke 調用中的匿名方法

[英]Anonymous method in Invoke call

我們想在 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;});

(警告:如果使用捕獲async ,你需要有點謹慎,但同步很好 - 即上面的很好)

另一種選擇是編寫擴展方法:

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基類中。

實際上您不需要使用委托關鍵字。 只需將 lambda 作為參數傳遞:

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

您需要創建一個委托類型。 匿名方法創建中的關鍵字“delegate”有點誤導。 您不是在創建匿名委托,而是在創建匿名方法。 您創建的方法可以在委托中使用。 像這樣:

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

為了完整起見,這也可以通過 Action 方法/匿名方法組合來完成:

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

我喜歡用 Action 代替 MethodInvoker,它更短而且看起來更干凈。

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";
}

我從來不明白為什么這會對編譯器產生影響,但這已經足夠了。

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 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM