C# WPF:将不可冻结的项目从一个调度程序转移到另一个调度程序
我们从XPS文档中加载FixedPage对象,处理并显示它。以下代码用于从包中加载FixedPage:C# WPF:将不可冻结的项目从一个调度程序转移到另一个调度程序,c#,wpf,dispatcher,C#,Wpf,Dispatcher,我们从XPS文档中加载FixedPage对象,处理并显示它。以下代码用于从包中加载FixedPage: FixedPage fp = null; Package package; // xps package Uri packageUri; // uri of the package in the package store Uri fixedPageUri; // uri of the fixed page
FixedPage fp = null;
Package package; // xps package
Uri packageUri; // uri of the package in the package store
Uri fixedPageUri; // uri of the fixed page
Dispatcher _mainDispatcher // reference to the main dispatcher, passed to this function
// this function runs in a different thread
// get the fixed page stream
Stream stream = package.GetPart(fixedPageUri).GetStream();
// create a parser context to help XamlReader with the resources used in the page
ParserContext pc = new ParserContext();
pc.BaseUri = PackUriHelper.Create(packageUri, fixedPageUri);
_mainDispatcher.BeginInvoke(
new UIRenderDelegate(delegate()
{
// this line takes its sweet time
fp = XamlReader.Load(stream, pc) as FixedPage;
stream.Dispose();
}), null).Wait();
// return the created fixed page;
但是,这个XamlReader.Load调用需要很长时间,特别是对于复杂的FixedPage,有时会阻塞UI。我们可以在另一个线程中使用它自己的Dispatcher来实现这一点,但是由于FixedPage类不是freeazable,它不能被主UI线程使用
有办法解决这个问题吗?现在我们无法使用RenderTargetBitmap将固定页面呈现为图像,因为BitmapSource是可自由释放的。首先将xaml加载到内存流中,然后将内存流传递给UI线程。在UI线程上解析memorystream。这样,您可以在后台线程上执行慢速文件IO。只有在UI线程上使用XamlReader.Load对流进行InMemory解析
这说明了如何操作。首先将xaml加载到内存流中,然后将内存流传递给UI线程。在UI线程上解析memorystream。这样,您可以在后台线程上执行慢速文件IO。只有在UI线程上使用XamlReader.Load对流进行InMemory解析
这说明了如何执行此操作。此函数已在其他线程中运行。begin调用用于在UI线程上运行加载。是的,我知道这一点。我的观点是保留两个线程,并在数据加载到内存后将数据从一个线程传递到另一个线程。现在,XamlReader.Load将更快,因此它可以在UI线程上完成,而不再是在后台线程中。在您的场景中,XamlReader.Load需要很长时间,因为所有文件都是IO。一旦数据进入MemoryStream,就不再需要那么多时间了。我有完全相同的问题,它对我有效。好的,有一件事不清楚,但这里是流在内存中。我们创建一个单页包。我仍然不明白你所说的另一部分[因此它可以在UI线程上完成,不再在后台线程中..],因为XamlReader.Load调用在UI线程中。是的,XamlReader.Load仍然在UI线程中。但是它现在要快得多,因为它不必从文件中加载XAML文本。它现在已经在内存中了。这项繁重的工作是在UI未被阻止的后台线程中完成的。您将memorystream传递给UIThread,然后在memorystream上调用XamlReader.Load。此函数已在其他线程中运行。begin调用用于在UI线程上运行加载。是的,我知道这一点。我的观点是保留两个线程,并在数据加载到内存后将数据从一个线程传递到另一个线程。现在,XamlReader.Load将更快,因此它可以在UI线程上完成,而不再是在后台线程中。在您的场景中,XamlReader.Load需要很长时间,因为所有文件都是IO。一旦数据进入MemoryStream,就不再需要那么多时间了。我有完全相同的问题,它对我有效。好的,有一件事不清楚,但这里是流在内存中。我们创建一个单页包。我仍然不明白你所说的另一部分[因此它可以在UI线程上完成,不再在后台线程中..],因为XamlReader.Load调用在UI线程中。是的,XamlReader.Load仍然在UI线程中。但是它现在要快得多,因为它不必从文件中加载XAML文本。它现在已经在内存中了。这项繁重的工作是在后台线程中完成的,在后台线程中UI没有被阻塞。您将memorystream传递给UIThread,然后在memorystream上调用XamlReader.Load。