2

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

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

所以,它是这样的:如果我想执行方法 void Update(),我必须去:

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

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

对于那里的每一种方法,这都是相当烦人的。我不能以某种方式自然地做到这一点,例如:

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

4 回答 4

2

简化事情的一种选择是添加扩展方法:

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

然后你可以使用:

this.BeginInvokeAction(action);

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

于 2013-04-05T13:23:13.560 回答
1

更新适用于 WPF !!!

您可以在匿名方法中使用短语法,甚至无需声明您的方法

  Dispatcher.BeginInvoke(DispatcherPriority.Background, new MethodInvoker(() =>   
                {
                   //Your Update code
                }));
于 2013-04-05T13:20:52.740 回答
0

尝试以下操作:

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

    }));
    else if(!this.controlname.IsDisposed)
   {
                           //AND here!
   }
于 2013-04-05T13:23:57.903 回答
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());
}

创建动作有一点开销,但它大大简化了代码,不必考虑各处的细节。

于 2013-04-05T13:41:41.743 回答