2011-04-24 25 views
2

我使用這個改變在其他線程的東西:MethodInvoker +拉姆達+論據+ CrossThread操作

 MethodInvoker m =() => { login_submit.Text = "Login"; }; 
     if (InvokeRequired) 
     { 
      BeginInvoke(m); 
     } 
     else 
     { 
      Invoke(m); 
     } 

這是工作的罰款。

我該如何通過argumets到那個lamba表達式?

我想做某事這樣的:

 MethodInvoker m = (string txt) => { login_submit.Text = txt; }; 
     if (InvokeRequired) 
     { 
      BeginInvoke(m); // I need to pass txt string in some way here. 
     } 
     else 
     { 
      Invoke(m); // I need to pass txt string in some way here. 
     } 
+0

什麼是「某事」? – 2011-04-24 13:14:09

+2

@Cody,我認爲這是「東西」的簡稱。 – svick 2011-04-24 13:16:08

回答

1

如果InvokeRequired是假的,那麼你就不需要擔心在所有調用任何東西 - 你已經在正確的線程上。

一個更好的解決方案可能是這樣的:當調用它

public delegate void InvokerDelegate(string data); 
public void DoStuff(string data){ 
    login_submit.Text = data; 
} 

然後執行:

if (InvokeRequired){ 
    Invoke(InvokerDelegate(DoStuff), "something"); 
} 
else{ 
    DoStuff("Something"); 
} 

,你會看到一個相當普遍的模式是爲功能做這樣的事情是在多線程環境下操作GUI

public delegate void InvokerDelegate(); 
public void DoGuiStuff(){ 
    if (login_submit.InvokeRequired){ 
    login_submit.Invoke(InvokerDelegate(DoGuiStuff)); 
    return; 
    } 

    login_submit.Text = "Some value"; 
} 

如果使用上述模式th e函數檢查是否需要調用,如果是這樣,則在正確的線程上調用它自己。然後它返回。當它自己調用時,檢查是否需要調用返回false,以免它再次調用自己 - 它只是運行代碼。

編輯:我剛回到winforms,並試圖使用該模式只花了幾分鐘的時間,試圖找出爲什麼我不能調用lambda。我想我最好回來並更新這個答案,以便在其他人試圖使用它的情況下添加所需的投射。

+0

public void delegate InvokerDelegate(string data);給我一個'無效令牌委託'錯誤。 – 2014-02-23 05:25:17

+0

Invoke(InvokerDelegate(DoStuff),「something」);讓我有一個'InvokerDelegate在當前上下文中不存在'錯誤 – 2014-02-23 05:30:30

+0

這應該是公共委託無效InvokerDelegate(字符串數據); (代表和無效關鍵字向後) – 2014-02-23 14:33:39

1

MethodInvoker是沒有任何參數的委託類型。如果我理解正確,可以這樣做:

string txt = "some text"; 
MethodInvoker m =() => { login_submit.Text = txt; }; 
0

您可以使用閉包將值傳遞到lambda的正文中。

string value = "Login"; 
MethodInvoker m =() => { login_submit.Text = value; }; 
if (InvokeRequired) 
{ 
    BeginInvoke(m); // I need to pass txt string in some way here. 
} 
else 
{ 
    Invoke(m); // I need to pass txt string in some way here. 
} 

,或者您可以使用類成員的數據

+0

我不明白這一點。 'login_submit.Text = value'如何? '通過什麼?這是不是隻執行內聯代碼? – 2014-02-23 05:32:55

2

如果這對你是一個常見的情況,我建議寫一個擴展方法:

public static class ControlExtensions 
{ 
    public static void EnsureInvokeAsync(this Control control, Action action) 
    { 
    if (control.InvokeRequired) control.BeginInvoke(action); 
    else action(); 
    } 
} 

class MyControl : UserControl 
{ 
    void M(string s) 
    { 
     // the lambda will capture the string in a closure 
     // the compiler does all the hard work for you 
     this.EnsureInvokeAsync(() => _button.Text = s); 
    } 
} 

此外,你應該考慮使用BackgroundWorker或任務異步操作。

+0

你的答案很好。但是因爲已經接受的答案有更多的細節,我現在不會更換接受的anser。但我愛它。對我從來沒有想過這件事感到羞恥。 – Hooch 2014-02-23 16:51:57