遗留代码性能问题 - 在第二个线程上创建 UIControl,而不仅仅是更改它

本文关键字:UIControl 创建 不仅仅是 线程 性能 代码 问题 第二个 | 更新日期: 2023-09-27 18:34:15

我继承了一个winforms应用程序。它使用第三方关闭的控件来呈现文档和照片...它只有用于打开文档的同步方法。问题是我的客户正在处理非常大的文档(在 2GB !! 的范围内(,打开这些文档确实"阻止"了 UI 线程......这很糟糕...

常识会让你认为"只需将其卸载到后台线程",但问题是"如何"!看,要更改控件(因为调用"Open"会导致它被更改(,我需要调用它,这会导致代码再次运行 o UI 线程......锁起来...

所以我把桌子倒过来了。如果我不是在主线程上创建控件并将其传递给后台线程进行处理,而是在后台线程上创建控件,加载它(避免这种方式跨线程异常(,并在完成后将其馈送到主线程?!?

现在我需要的是知道如何明确地将一个控件处理到另一个线程,而不仅仅是暂时......

遗留代码性能问题 - 在第二个线程上创建 UIControl,而不仅仅是更改它

我不确定这是否可能,但您可以尝试:

  • 在辅助线程上创建一个新窗体(此窗体将托管您的花哨控件(
  • 从此辅助 UI 加载文档。它将被阻止,但您可以隐藏它,只显示一个在主 UI 上加载消息。
  • 作业完成后,将"工作"转移到主 UI 和主线程。

这只是一个想法。

你要求做的事情是不可能的。Winforms 控件的线程相关性是在创建该控件时确定的,并且无法更改。

最好的解决方案是不使用该控件。我怀疑它所做的任何事情都无法由其他人正确和胜任地实施。

如果您可以在第二个 STA 线程中运行完全不同的窗口,那么这将是下一个最好的选择。该特定窗口在文档加载时仍将冻结,但至少您的主 UI 仍然可以。请注意,不应尝试在同一窗口中混合和匹配来自不同线程的控件;这将导致各种头痛。

最后,作为一个完整的黑客,您可以考虑继续在后台线程中调用此Open()方法,尽管控件由主 UI 线程拥有。不可否认,控件实际尝试访问 UI 组件本身的唯一时间是在 Open() 方法操作的最后,您可以继续捕获抛出的InvalidOperationException,并将其用作文档加载已完成的信号。然后只需使主 UI 线程中的控件失效即可。

我会给出最后一个建议的几率不超过 50/50。这将取决于控件实际对加载的数据执行的操作,如果它是某种复合控件,它依赖于实际获取其加载的结果并将其作为 Open() 方法的一部分复制到控件,则该部分可能会失败,并且控件最终不会正确初始化。