[英]How to fill a List<T> on the main-thread using Parallel.For(..)
[英]How can I create controls in a non main-thread?
在我们的应用程序中,我们可以打印报告。 对于这些报告,我们使用诸如FlowDocument,Canvas之类的类以及诸如Labels之类的其他控件。 由于仅应在主线程中创建控件,因此应用程序将显示一个通知窗口,用户必须等待。 一个报告最多可以包含100页,因此这可能需要几分钟。 用户无法使用该应用程序执行其他任何操作。
反正有摆脱这种情况的方法吗?
我发现问题不在于在新线程中完全创建文档。 我可以做这个。 但是之后我无法显示该文档,因为它不是由主线程创建的。 如果我在主线程中创建它-这就是我所做的-它可以正常工作。 但是随后在生成报告时阻止了该应用程序。
有什么方法可以将对象的所有权转移到另一个线程? 特别是对于UI元素(例如Canvas)? 就像我说的那样,我能够在其他线程中创建报告,但是应用程序拒绝显示它。 无法显示未由主线程创建/拥有的控件。
你不能 任何UI控件都必须由Dispatcher
管理
如果绝对需要从另一个线程创建控件,则需要通过主Dispatcher调用它们的创建/添加,同步或异步(取决于您的选择)
异步调用的快速示例(将BeginInvoke
更改为Invoke
进行同步,并相应地使用DispatcherPriority
进行播放)
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
// Your control creation here
}), DispatcherPriority.Background);
我曾经处理过一个类似的问题:Global DockManager
,动态处理停靠的内容,我不得不从Dispatcher创建控件,以便能够将它们实际添加到DockManager
。 确保通过这些电话避免任何比赛情况,并且应该没事
我建议创建一个带有调度程序的新线程。 在这个单独的线程中,您可以创建元素树,并将其显示在独立于主窗口UI线程的单独窗口中。 然后用户可以选择是否打印。
若要使用初始化的WPF调度程序创建新线程,可以使用以下代码:
public class DispatcherBuilder : IBuilder<Dispatcher>
{
public Dispatcher Build()
{
Dispatcher dispatcher = null;
var manualResetEvent = new ManualResetEvent(false);
var thread = new Thread(() =>
{
dispatcher = Dispatcher.CurrentDispatcher;
var synchronizationContext = new DispatcherSynchronizationContext(dispatcher);
SynchronizationContext.SetSynchronizationContext(synchronizationContext);
manualResetEvent.Set();
Dispatcher.Run();
});
thread.Start();
manualResetEvent.WaitOne();
manualResetEvent.Dispose();
return dispatcher;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.