拥有一个大多数属性非常轻量级的对象 - 最多 200 个字符的文本。一个属性是 FlowDocument,它可能很大并且想要异步检索它。当我设置 Async = True 并显示以下消息时它失败:“调用线程无法访问此对象,因为不同的线程拥有它。”
<FlowDocumentReader Name="FlowDocumentPageViewer1" HorizontalAlignment="Stretch"
Document="{Binding Source={x:Static Application.Current}, Path=MyGabeLib.Search.SelectedDoc.DocFlowDocument, Mode=OneWay, IsAsync=True}" />
Production Get 更复杂,但在 IsAsyc True 上同样失败,即使使用简单的硬编码 FlowDocument。
public FlowDocument DocFlowDocument
{
get
{
FlowDocument docFlowDocumentFast = new FlowDocument();
Paragraph p = new Paragraph();
Run r = new Run();
r.Foreground = System.Windows.Media.Brushes.Red;
r.Text = "Hard Code Simple FlowDocument";
p.Inlines.Add(r);
docFlowDocumentFast.Blocks.Add(p);
return docFlowDocumentFast;
}
{
它确实调用 SelectedDoc.DocFlowDocument 并返回文档!使用 IsAsync = False 它运行得很好。我认为问题在于静态源,但显然我不知道如何解决它。
public partial class App : Application
{
private static GabeLib staticGabeLib = new GabeLib();
private GabeLib myGabeLib = staticGabeLib;
public GabeLib MyGabeLib
{ get { return myGabeLib; } }
public static GabeLib StaticGabeLib
{ get { return staticGabeLib; } }
}
当 GabeLib 启动时,它会从数据库中读取应用程序和用户设置。
如果有更好的方法来解决这个问题,我会试一试。由于 FlowDocument 可以是 3 mb 并且所有其他属性 10K 结合起来,这对性能有很大影响,最常用的按钮是下一个对象。FlowDocument 来自 SQL 中的 varchar(max),并使用换行符和突出显示的单词进行格式化。它不仅很大 - 与其他房产相比,它也很昂贵。
FlowDocumentReader 本身似乎有一些异步支持,因为在大型文档上我快速获得第一页,然后页面以大约 100/秒的速度加载。但我仍然希望它在检索到所有其他属性后获得第 1 页。
问题正如马丁所说“由于 FlowDocument 是一个调度程序对象,它只能从创建它的线程访问”。
解决方案是序列化为 XAML 字符串。
public string XAMLdocFlowDocument
{
get
{
Thread.Sleep(6000);
return XamlWriter.Save(FlowDocumentSlow);
}
}
使用转换器绑定到字符串
<FlowDocumentReader Grid.Row="3" Grid.Column="0" VerticalAlignment="Stretch"
Document="{Binding Path=XAMLdocFlowDocument, IsAsync=True,
Converter={StaticResource flowDocumentToXamlConverter}, Mode=OneWay}" />
转换器
[ValueConversion(typeof(string), typeof(FlowDocument))]
public class FlowDocumentToXamlConverter : IValueConverter
{
#region IValueConverter Members
/// <summary>
/// Converts from XAML markup to a WPF FlowDocument.
/// </summary>
public object Convert(object value, System.Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
var flowDocument = new FlowDocument();
if (value != null)
{
var xamlText = (string)value;
flowDocument = (FlowDocument)XamlReader.Parse(xamlText);
}
// Set return value
return flowDocument;
}