使用 Dispatcher.Invoke 更新 UI 时遇到问题
我正在开发一个基于插件的 WPF 应用程序。插件使用多个线程并行加载。其中一个插件是使用 WPF RibbonWindow 的 UI 插件。我正在尝试将插件 A 中的 RibbonTab 添加到 UI 插件中。
由于调用线程不拥有 RibbonWindow,因此我在 RibbonWindow 上使用 Dispatcher.Invoke。不幸的是,委托内部的代码永远不会被调用。应用程序仍具有响应能力,但未添加选项卡。
我是否可以从另一个插件访问 UI 线程? 我是否可以拥有一个可以在整个应用程序中保持活动状态的线程,以便我使用该线程在 RibbonWindow 上进行操作?
System.Threading.ThreadStart start = delegate()
{
log.Debug(Thread.CurrentThread.ManagedThreadId);
if (!this.Dispatcher.CheckAccess())
{
this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate() {
log.Debug(Thread.CurrentThread.ManagedThreadId);
ribbonRoot.Items.Add(myRibbonTab);
});
}
else {
log.Debug("We have access add directly.");
}
};
new Thread(start).Start();
如果您需要任何其他信息,请告诉我。
谢谢。
I am working on a plugin based WPF Application. The plugins are loaded parallely using multiple threads. One of the plugins is a UI plugin that uses a WPF RibbonWindow. I am trying to add a RibbonTab from Plugin A to the UI plugin.
Since the calling thread does not own the RibbonWindow, I am using the Dispatcher.Invoke on the RibbonWindow. Unfortunately the code inside the delegate is never being called. The application is still responsive, but the tab is not being added.
Is there anyway I can access the UI thread from another plugin?
Can I have a thread that can be kept alive all through my application, for me to use that Thread for operating on the RibbonWindow?
System.Threading.ThreadStart start = delegate()
{
log.Debug(Thread.CurrentThread.ManagedThreadId);
if (!this.Dispatcher.CheckAccess())
{
this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate() {
log.Debug(Thread.CurrentThread.ManagedThreadId);
ribbonRoot.Items.Add(myRibbonTab);
});
}
else {
log.Debug("We have access add directly.");
}
};
new Thread(start).Start();
Please let me know if you need any additional information.
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您需要
Application.Current.Dispatcher
在 UI 线程上调用它。顺便说一句:你为什么要转换到 ThreadStart? (不重要,只是好奇)
You need the
Application.Current.Dispatcher
to invoke it on the UI thread.btw: Why are you casting to ThreadStart? (not important, just curious)
如果您只想添加功能区选项卡,则无需为其启动线程(您已经将其分派到 UI 线程),除非您想在该线程上执行更多操作。即使如此,使用 ThreadPool 而不是创建新线程可能会更好。无论如何,在这样的场景中,我通常通过插件接口将
Dispatcher
从主窗口传递到插件,而不是直接访问Application.Current.Dispatcher
。使其更加封装,并且您可以在单元测试中更好地控制它。If you just want to add the ribbon tab you don't need to start a thread for it (you are already dispatching it to the UI thread) unless there is more you want to do on the thread. Even then it might be better to use the
ThreadPool
instead of creating a new thread. Any way, in scenarios like this I usually pass theDispatcher
from the main window to the plugin via the plugin interface instead of directly accessing theApplication.Current.Dispatcher
. Makes it more encapsulated and you have better control over it in unit tests.