2011-04-24 30 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