【发布时间】:2012-04-05 13:00:48
【问题描述】:
我在我的项目中使用了一个可视控件,该控件来自我没有源代码的库。
一次在屏幕上使用其中三个控件来更新(大约 200 毫秒)以获得良好的 UI 响应需要太长时间。 (我可能需要一次更新所有三个,这让我的 UI 在他们都在思考的时候卡住了大约 600 毫秒)。
我已经阅读了一些关于 TaskScheduler 的帖子,并开始研究并行任务功能,作为在它们自己的线程中运行每个控件的一种方式。该平台将是多核的,所以我想利用同步处理。
但问题是我什至不知道我不知道该怎么做..
是否有合适的设计模式可以在 WPF 中与主 UI 线程分开的线程中运行控件?
特别是:它是第三方地图控件,当给定新位置或缩放级别时,重绘需要很长时间(~200 毫秒)。也许其中三个更新频率最高为 4Hz - 显然他们不会跟上..
我已经将 WPF 控件封装在一个用户控件中,并且需要在它自己的线程中运行每个实例,同时仍然捕获用户输入(例如鼠标点击)。
更新:虽然我正在寻找解决方案,但到目前为止我已经实现了以下内容。
我的主 (UI) 线程生成一个线程,该线程创建一个包含相关控件的新窗口,并将其定位在正确的位置(因此它看起来只是一个普通控件)。
_leftTopThread = new Thread(() =>
{
_topLeftMap = new MapWindow()
{
WindowStartupLocation = WindowStartupLocation.Manual,
Width = leftLocation.Width,
Height = leftLocation.Height,
Left = leftLocation.X,
Top = leftLocation.Y,
CommandQueue = _leftMapCommandQueue,
};
_topLeftMap.Show();
System.Windows.Threading.Dispatcher.Run();
});
_leftTopThread.SetApartmentState(ApartmentState.STA);
_leftTopThread.IsBackground = true;
_leftTopThread.Name = "LeftTop";
_leftTopThread.Start();
其中CommandQueue 是Thread-safe BlockingCollection 队列,用于向地图发送命令(移动位置等)。
现在的问题是我可以任一
- 由于
System.Windows.Threading.Dispatcher.Run()调用而获得用户输入 - 或者阻塞在CommandQueue上,监听主线程发送的命令
我无法等待命令,因为它会占用我所有的线程 CPU!
是否可以阻止和让事件消息泵工作?
【问题讨论】:
-
所有 WPF 控件都必须在 UI 线程上更新。但是,如果您提供您正在使用的控件的一些详细信息以及您为更新/填充它而编写的任何代码,我们可能会提供帮助。
-
@CameronPeters,你确定不能有多个“UI 线程”吗?
-
我目前有多个“UI”线程正在运行(感谢 Threading.Dispatcher.Run()),但无法阻止它们等待信号。
-
@svick -- 是的,可以有多个 UI 线程。但是,所有 WPF 控件都来自 System.Windows.Threading.DispatcherObject,这需要线程关联。任何控件只能由创建它的线程更新。后台线程可以做一些工作,但必须将结果分派给创建控件的线程,然后该线程才能进行更新...
标签: c# wpf multithreading task-parallel-library blocking