C# 跨线程操作无效,2 个控件和 2 个单独的线程
本文关键字:线程 控件 单独 操作 无效 | 更新日期: 2023-09-27 18:16:54
这是我正在尝试做的一个简化的例子:
我有 2 个控件MyControl c
和Panel p
. p
正常在主 GUI 线程中创建,但我希望在后台线程中创建c
,因为这需要一段时间,而且我不想冻结 GUI。 如何将c
添加到p.Controls
? 如果我在this.Invoke
中这样做,它会为c
抛出异常,如果我从后台线程中这样做,它会为p
抛出异常。
还是我真的不应该在主 GUI 线程之外创建 GUI 元素?
是还是我真的不应该在主 GUI 线程之外创建 GUI 元素?
的,这基本上是问题所在。 大多数控件具有线程相关性,必须在用户界面线程中创建。
通常,处理此问题的方法是将导致控件创建缓慢的"工作"移动到后台线程上,但仍在 UI 线程上创建控件。 然后,您可以使用 Control.Invoke 或 Control.BeginInvoke 在缓慢的工作完成后更新 UI 中的信息。
例如,如果要从某个外部源加载一组数据,则可以创建控件,并启动后台线程来加载数据。 加载数据后,可以更新控件以反映它。 这将导致它始终保持响应。
不需要很长时间; 相反,获取其数据需要很长时间。在这种情况下,请考虑创建一个控件,该控件可以在填充时将其显示为 UI。然后,可以在主线程中创建控件,在后台线程中填充它,并为用户提供更好的体验。
使用后台线程执行它必须执行的操作,然后以某种方式(bool _backgroundCompleted
作为一个微不足道的示例(发出信号,表明c
已准备好创建。
从Timer
创建c
,这些会定期触发并且在设置_backgroundCompleted
之前不执行任何操作,然后创建c
,然后终止计时器。
它可能很"丑陋",但它会起作用并保持简单。
Forms.Timer
,如果你问;)
是的,永远不要弄乱同一表单上的多个线程。 您可以在多个线程上拥有多个表单,但要做到这一点,您必须首先运行一个新线程,然后在其上创建一个表单。 它将有自己的消息循环,并且会做得很好。