我正在使用一个 winforms 控件,它既是一个 GUI 元素,又执行一些尚未向开发人员公开的内部处理。当这个组件被实例化时,可能需要 5 到 15 秒的时间才能准备好,所以我想做的就是将它放在另一个线程上,完成后将其带回 gui 线程并将其放在我的表单上。问题是这将(并且已经)导致跨线程异常。
通常,当我使用工作线程时,它只使用简单的数据对象,当处理完成时我可以推迟,然后使用主线程上已有的控件,但我从来不需要以这种方式移动整个控件。
有谁知道这是否可能,如果可能的话如何?如果不是,如何处理这样有可能锁定主 GUI 的问题?
你不需要锁定GUI,你只需要调用invoke:
Windows 窗体中的控件绑定到
特定线程和非线程
安全的。因此,如果您正在调用
控制方法不同
线程,您必须使用其中之一
控件的调用方法来编组
对正确线程的调用。这
属性可用于确定是否
您必须调用一个调用方法,该方法
如果您不知道什么,可能会很有用
线程拥有一个控件。ref http://msdn.microsoft.com/en-us/library/system.windows.forms.control.invokerequired.aspx
代码如下:
public delegate void ComponentReadyDelegate(YourComponent component);
public void LoadComponent(YourComponent component)
{
if (this.InvokeRequired)
{
ComponentReadyDelegate e = new ComponentReadyDelegate(LoadComponent);
this.BeginInvoke(e, new object[]{component});
}
else
{
// The component is used by a UI control
component.DoSomething();
component.GetSomething();
}
}
// From the other thread just initialize the component
// and call the LoadComponent method on the GUI.
component.Initialize(); // 5-15 seconds
yourForm.LoadComponent(component);
通常调用LoadComponent
从另一个线程调用将导致跨线程异常,但通过上述实现,该方法将在 GUI 线程上调用。
InvokeRequired
告诉你如果:
调用者必须调用调用方法
当进行方法调用时
控制,因为调用者位于
与该线程不同的线程
控件创建于。ref http://msdn.microsoft.com/en-us/library/system.windows.forms.control.invokerequired.aspx
Update:
因此,如果我理解正确的话,控制对象是在 GUI 线程以外的线程上创建的,因此即使您能够将其传递给 GUI 线程,您仍然无法在不导致跨线程异常的情况下使用它。解决方案是在 GUI 线程上创建对象,但在单独的线程上初始化它:
public partial class MyForm : Form
{
public delegate void ComponentReadyDelegate(YourComponent component);
private YourComponent _component;
public MyForm()
{
InitializeComponent();
// The componet is created on the same thread as the GUI
_component = new YourComponent();
ThreadPool.QueueUserWorkItem(o =>
{
// The initialization takes 5-10 seconds
// so just initialize the component in separate thread
_component.Initialize();
LoadComponent(_component);
});
}
public void LoadComponent(YourComponent component)
{
if (this.InvokeRequired)
{
ComponentReadyDelegate e = new ComponentReadyDelegate(LoadComponent);
this.BeginInvoke(e, new object[]{component});
}
else
{
// The component is used by a UI control
component.DoSomething();
component.GetSomething();
}
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)