2013-04-05 65 views
2

我正在使用线程在我的程序的UI中运行长操作,以便它不锁定。但是,在这些任务中,我需要更新控件,这不可能来自创建它们的线程。建议使用control.BeginInvoke(Delegate)来执行你想要的方法。C#Control.Invoke方法组

但是,要做到这一点,你必须声明一个委托类型,然后才可以调用它们。

因此,它是这样的:如果我想执行方法无效更新(),我必须去:

delegate void CallbackVoid(); 
void Update() {...} 

...(in task code)... 
this.BeginInvoke(new CallbackVoid(Update)); 

这是相当烦人对于每个单独的方法做出来那里。我不能只是以某种方式做到这一点自然,如:

void Update() {...}  
this.BeginInvoke(Update); 

回答

1

修订作品WPF!

您可以使用匿名方法短的语法,甚至没有宣布你的方法,其简化的东西

Dispatcher.BeginInvoke(DispatcherPriority.Background, new MethodInvoker(() => 
       { 
        //Your Update code 
       })); 
+0

与control.Invoke(新的EventHandler(代表 {/ *更新控制在这里* /})); ?哪个更好? – Arie 2013-04-05 13:24:24

+0

@Arie两者都是正确的,但不是其他。 MSDN表示:“委托可以是EventHandler的一个实例,在这种情况下,sender参数将包含此控件,而Event参数将包含EventArgs.Empty。委托也可以是MethodInvoker的实例或任何其他代理一个void参数列表,对EventHandler或MethodInvoker委托的调用将比对另一个委托类型的调用快得多“ – Alex 2013-04-05 13:28:42

+0

@voo:实际上,这个*对于Windows窗体不是正确的,这就是问题的症结所在... – 2013-04-05 13:41:42

2

一种选择是添加一个扩展方法:

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

然后,你可以使用:

this.BeginInvokeAction(action); 

这个工程的原因是我们是现在为编译器提供具体的委托类型以将方法组转换为。

0

尝试以下操作:

if (this.controlname.InvokeRequired && !this.controlname.IsDisposed) 
       { 
        Invoke(new MethodInvoker(delegate() 
         { 
          //Update control on GUI here! 

    })); 
    else if(!this.controlname.IsDisposed) 
    { 
          //AND here! 
    } 
+0

这实际上是*更多*代码,而不是更少,并且没有任何其他解决方案的优势。整个想法是OP *知道*他是而不是在UI线程中;不需要检查,并且他知道这些控件不会被丢弃(如果不是这样,它确实会更好,因此您可以找到/修复该错误,而不是静静地继续)。 – Servy 2013-04-05 13:37:20

0

BeginInvoke是异步的,Invoke是同步的,你用哪一个取决于你想要做什么。如果您在继续之前需要完成呼叫,则需要同步呼叫。

这是我最喜欢的同步所调用的结构:

static void InvokeIfRequired(Control control, Action action) 
{ 
    if (control.InvokeRequired) 
    { 
     control.Invoke(action); 
    } 
    else 
    { 
     action.Invoke(); 
    } 
} 

使用:

void MyTestFunction() 
{ 
    InvokeIfRequired(myControl,() => 
     { 
      MyFunction(); 
      MyOtherFunction(); 
     }); 

    // Or more simply: 
    InvokeIfRequired(myControl,() => MyFunction()); 
} 

有在创建行动的一个小的开销,但它简化了代码颇有几分不必须考虑到处处的细节。