C#Control.Invoke方法组

时间:2013-04-05 13:17:56

标签: c# multithreading delegates invoke

我正在使用线程在程序的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 个答案:

答案 0 :(得分:2)

简化事情的一个选项是添加扩展方法:

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

然后你可以使用:

this.BeginInvokeAction(action);

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

答案 1 :(得分:1)

更新为WPF工作!!!

您可以使用匿名方法的短语法,甚至不用声明您的方法

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

答案 2 :(得分:0)

尝试以下方法:

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

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

答案 3 :(得分: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());
}

Action的创建有一点开销,但它简化了代码,无需在任何地方考虑细节。