让大多数属性的对象非常轻量级 - 文本最多200个字符。一个属性是FlowDocument,它可以很大并且想要检索它Async。当我使用以下消息设置Async = True时失败:“调用线程无法访问此对象,因为另一个线程拥有它。”
<FlowDocumentReader Name="FlowDocumentPageViewer1" HorizontalAlignment="Stretch"
Document="{Binding Source={x:Static Application.Current}, Path=MyGabeLib.Search.SelectedDoc.DocFlowDocument, Mode=OneWay, IsAsync=True}" />
生产获取更复杂,但即使使用简单的硬编码FlowDocument,IsAsyc True也会失败。
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;
}
答案 0 :(得分:2)
在没有看到代码的情况下,我猜测在读取属性时会创建(并加载)FlowDocument。这是在后台线程中完成的,因为属性绑定是异步的。
由于FlowDocument是一个调度程序对象,因此只能从创建它的线程访问它,在这种情况下,它是读取属性的后台线程。
因此,您的UI线程无法访问创建的FlowDocument。
您需要另一种方法来异步加载文档。
也许您可以使用同步(普通)绑定并使用XamlReader.LoadAsync加载文档?我自己没试过,但我猜它值得尝试。