在WinForms中保留对控件的全局引用以访问GUI线程 [英] Keeping a global reference to a control in WinForms for accessing GUI thread
问题描述
(这个问题有一点点历史,请忍受)
在这个问题中,我谈到了集中更新更新GUI所需的跨线程"轨迹的可能性,如下所示:
In this question, I talked about the possibility of centralising the 'cross thread' hocus-pocus that is required for updating the GUI like so:
//Utility to avoid boiler-plate InvokeRequired code
//Usage: SafeInvoker.Invoke(myCtrl, () => myCtrl.Enabled = false);
public static void Invoke(Control ctrl, Action cmd)
{
if (ctrl.InvokeRequired)
ctrl.BeginInvoke(new MethodInvoker(cmd));
else
cmd();
}
上周,考虑到在处理事件时总是会发生这种情况(在我的代码中),并且部分受
Last week, mulling over the fact that this always happens (in my code) when handling an event, and partly inspired by Dustin Campbell's event extension method, I cooked up this:
//Utility to avoid boiler-plate SafeInvoker.Invoke code
//Usage obj.EventRaised += obj_EventRaised.OnGUIThread(controlreference);
public static EventHandler OnGUIThread(this EventHandler h, Control ctrl)
{
// lambda expressions are not syntactic sugar, they are syntactic crack!
return (s, e) => SafeInvoker.Invoke(ctrl, () => h(s, e));
}
困扰我的地方总是必须要有一个控制权.据我所知,只有一个GUI线程,因此任何控件都可以在这里进行.
The thing that bugs me here is always having to have a control to hand. As far as I know, there is only one GUI thread, so any control would do here.
我想知道是否要创建一个'GUIContext'单例,并在应用程序启动时将其扔给我的主窗体引用,然后从我的扩展方法中访问它,从而消除了对ctrl参数的需要.
I got to wondering about creating a 'GUIContext' singleton and throwing it a reference to my main form when the application starts up, then accessing that from my extension method, thus removing the need for the ctrl parameter.
这是个坏主意吗?如果是,为什么?有更好的方法吗?我知道在Rx中有上下文的概念,但是我不知道任何与香草WinForms等效的东西.我可以想象如果我尝试更新尚未处理的控件可能会出现问题(但在那种情况下,我
Is this a bad idea, and if so, why? Is there a better way to do it? I know that in Rx there is a notion of Context, but I'm not aware of anything equivalent in vanilla WinForms. I can imagine there might be a problem if I try to update a control that is not yet handled (but in that case I'm screwed anyway).
推荐答案
执行此操作会将您限制在一个主窗体和一个GUI线程中.但是,除了任何其他内容外,.NET表单(和基础Win32 API)也都需要主要的GUI线程,因此它不太可能改变.
Doing this would restrict you to a single main form and a single GUI thread. But the need for a main GUI thread is as much a requirement of .NET forms (and the underlying Win32 API) as anything, so it's not very likely to change.
您会知道应用的单一主表单是否可能会更改.即使这样做,与将表单传递给所有后台线程相比,单例还是更好的跟踪哪个表单是主表单"的地方.
You would know if having A single main form for your app is likely to change or not. Even if it it did, your singleton would be a better place to keep track of which form was "main" than to pass that around to all of the background threads.
总的来说,这对我来说似乎是一个合理的设计.我使用全局变量将hwndMain保留在非托管应用程序中已有十多年了,从不后悔.
On the whole, this looks like a reasonable design to me. I've used a global variable to hold hwndMain in my unmanaged apps for more than a decade and never regretted it.
这篇关于在WinForms中保留对控件的全局引用以访问GUI线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!