.net - 在非 UI 线程中创建控件

标签 .net winforms multithreading controls

我有一种插件模型,其中各种复杂的用户控件存储在 DLL 中,并在运行时使用

Activator.CreateInstanceFrom(dllpath, classname).

由于我正在加载其中的很多内容,因此我想在后台执行此操作,通过创建一个新线程来进行加载,以保持 UI 响应。然后,控件作为主窗体的父级,并在需要时显示。

这似乎工作正常 - 直到我尝试在这些用户控件之一上的任何嵌套控件上设置任何属性,例如在按钮的事件处理程序中,它会引发跨线程异常。我确实意识到我可以通过在每次访问属性时检查 InvokeRequired 来避免这种情况,但我宁愿在为用户控件编写代码时不必担心这一点(特别是因为还有其他人也在编写这些代码,他们可能不总是记得)。

所以我的问题是,有没有什么安全的方法可以做我正在尝试的事情,或者我应该如何最好地在后台加载这些控件?或者它基本上是不可能的,我是否必须坚持主线程来创建控件?

我希望我提供的信息足以说明我的情况;如果不是,我很乐意详细说明并提供代码示例。

最佳答案

可以在后台加载 DLL 并创建控件对象,但是必须将控件添加到主线程中的窗体中,并且所有用户交互以及控件属性的任何编程更改(在创建之后)都必须发生在主线程中。正如您可能已经知道的那样,根本没有办法解决这个问题。现在,除非这些 DLL 的加载和控件创建需要很长时间,否则我认为没有理由在单独的后台线程中执行此操作。

如果控件执行的某些操作阻塞了 UI,而您希望它们在后台发生,这是另一回事,您最好单独考虑每个操作,并创建显式方法来在 UI 线程和后台线程之间进行通信。

尝试做一个通用的万能框架,在 UI 线程模式和后台模式下工作相同,并且只检查 InvokeRequired 结果有时性能更差(因为所有线程在 Invoke 中被阻塞)甚至(未检测到)死锁一旦应用程序达到合理的复杂性。在 BeginInvoke 中异步执行所有更新,而不单独考虑每个方法,可能会导致数据一致性问题(即,由于线程之间调用顺序的颠倒,控件可能会及时将自己更新为状态)。

关于.net - 在非 UI 线程中创建控件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1040770/

相关文章:

c - C 中的多线程 : passing a structure

java - 使用参数创建新线程 - 线程已创建但不显示数据

c# - 将60m记录导入SQL的最快方法是什么

c# - ScopeLock 模式 : Struct or Class?

c# - 从 Windows 窗体中删除控件并调整其他控件以适应

c# - 每天创建一个新的日志文件

c++ - 将 "this"传递给线程 C++

C# 相当于字段的 typeof

.net - 如何使用服务帐户向Google v3 api进行身份验证

winforms - DevExpress 中的 DisplayText 自动过滤