我正在使用线程在程序的UI中运行长时间的操作,这样它就不会锁定。但是,在那些任务中,我需要更新控件,这是不可能的,不是从他们创建的线程。建议使用control.BeginInvoke(Delegate)来执行所需的方法。
但是,要做到这一点,你必须声明一个委托类型,然后才能调用它们。
所以,它是这样的:如果我想执行方法void Update(),我必须去:
delegate void CallbackVoid();
void Update() {...}
...(in task code)...
this.BeginInvoke(new CallbackVoid(Update));
对于那里的每一种方法来说,这都是相当无聊的。我不能以某种方式自然地做到这一点,如:
void Update() {...}
this.BeginInvoke(Update);
答案 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的创建有一点开销,但它简化了代码,无需在任何地方考虑细节。