我知道 GUI 组件不能从不同的线程中使用。所以你通常会做一个检查InvokeRequired
,然后调用Invoke
等的方法。但这是很多代码。有什么办法可以做这样的事情:MyEvent += myDelegate
这个 myDelegate 将从分配它的线程执行?为什么 Invoke 方法只能从Control
类中获得?我唯一的想法是制作自己的方法,如 AddDelegate (delegate.. , Control c) 或类似的东西。
知道如何实现这一目标吗?
我知道 GUI 组件不能从不同的线程中使用。所以你通常会做一个检查InvokeRequired
,然后调用Invoke
等的方法。但这是很多代码。有什么办法可以做这样的事情:MyEvent += myDelegate
这个 myDelegate 将从分配它的线程执行?为什么 Invoke 方法只能从Control
类中获得?我唯一的想法是制作自己的方法,如 AddDelegate (delegate.. , Control c) 或类似的东西。
知道如何实现这一目标吗?
为了避免这样的重复代码,我通常会创建一个类来隔离这个逻辑。当应用程序启动时,我初始化这个类并在整个应用程序中使用它。优点是它可以在控件之外使用。
public static class UI
{
private static Control internalControl;
public static void Initialize(Control control)
{
internalControl = control;
}
public static void Invoke(Action action)
{
if (internalControl.InvokeRequired)
{
internalControl.Invoke(action);
}
else
{
action();
}
}
}
主窗体初始化时初始化:
UI.Initialize(this);
用法:
UI.Invoke(() => { this.Text = "Test"; });
我使用了一个相当简单的方法:
private void execThreadSafeMethod(Control ctrl)
{
MethodInvoker method = (MethodInvoker) delegate
{
//Do something that you always wanted to do :)
}
if(ctrl.InvokeRequired == true)
{
ctrl.Invoke(method);
}
{
method.Invoke();
}
}
您使用的是 .Net 4 吗?如果是这样,您可以使用异步任务。
您将从创建控件的主线程的同步上下文中创建一个 TaskScheduler。
var uiTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
然后,您可以在后台线程上运行的任何方法中使用它来更新主线程上的任何控件。
Task.Factory.StartNew(
() => { MessageBox.Show("Message from separate thread.") },
CancellationToken.None,
TaskCreationOptions.None,
uiTaskScheduler);
一直在等待找到我的方法,但我没有看到它(希望我没看错)
这就是我在单独的线程中处理调用的方式:
this.Invoke((MethodInvoker)delegate() { /*whatever I need done*/ });
这很好,因为您可以将代码保留在适用的地方而不是乱跳
this.Invoke((MethodInvoker)delegate() {
//here is some code I need to run on the main thread
//usually making a label visible or some other bs
//might want to resize my form or update a list box, who knows
});