【发布时间】:2014-12-15 18:21:24
【问题描述】:
我继承了一个 winforms 应用程序。它使用呈现文档和照片的第三方封闭控件......它只有用于打开文档的同步方法。问题是我的客户正在处理非常大的文档(在 2GB 的区域!!!)并且打开这些文档真的“阻塞”了 UI 线程......这很糟糕......
常识会让您认为“只需将其卸载到后台线程”,但问题是“如何”!看,要更改控件(因为调用“打开”会导致它被更改)我需要 Invoke 它,这会导致代码再次在 UI 线程上运行...锁定它...
所以我把桌子倒过来了。如果不是在主线程上创建控件并将其传递给后台线程进行处理,我可以在后台线程上创建控件,加载它(避免这种方式的跨线程异常),完成后,馈送它到主线程?!?
现在我需要知道如何明确地处理对另一个线程的控制,而不仅仅是暂时...
【问题讨论】:
-
必须设计控件来支持这一点,而且可能并非如此。听起来它的核心设计只是有缺陷。唯一真正好的解决方案是解决这个问题,如果没有能力打开它,你可能无法做到这一点。
-
是的。听起来完全像是“我们只有一把锤子和一个不称职的工匠,所以我们将这个控件设计成看起来像钉子”。绝对不在大文件上使用它 - 或者他们接受了这个问题。与供应商交谈,他们将不得不解决这个问题。从头到尾都没有办法做到这一点。
-
请注意,从后台线程调用 Invoke 一次不需要占用 UI 线程很长时间。如果加载任务是无 GUI 的,并且只需要更新 GUI 中的进度条,则使用 Invoke 更新进度条不会将 UI 占用很长时间,因此 UI 将保持响应.最大的麻烦将是如何正确地将加载的文档从后台线程传递到 GUI 线程——我不太了解的问题(与处理器缓存和内存可见性有关)但 @Servy 可能会。
-
(我上面的评论依赖于有一个无 GUI 的数据模型,一旦数据加载完成,该模型可用于填充第三方控件。如果“加载”真的只是添加的过程数据直接从文件到第三方控件,然后在后台线程上加载不会给你带来太多好处,除了你会有许多对 Invoke 的简短调用,GUI 线程可以在这些调用之间处理其他事件,这意味着你的 GUI 将保留至少有点反应。)
标签: c# multithreading