1

ほとんどのプロパティを持つオブジェクトを非常に軽量にします - テキストは最大 200 文字です。1 つのプロパティは、大きくなる可能性があり、非同期で取得したい 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;
        }
4

1 に答える 1

2

コードを見ずに、プロパティが読み取られたときにFlowDocumentが作成(およびロード)されると推測しています。プロパティバインディングは非同期であるため、これはバックグラウンドスレッドで実行されます。

FlowDocumentはディスパッチャオブジェクトであるため、FlowDocumentを作成したスレッド(この場合はプロパティを読み取るバックグラウンドスレッド)からのみアクセスできます。

そのため、作成されたFlowDocumentにUIスレッドからアクセスすることはできません。

ドキュメントを非同期でロードするには、別のアプローチが必要になります。

おそらく、同期(通常)バインディングを使用し、 XamlReader.LoadAsyncを使用してドキュメントをロードできますか?自分で試したことはありませんが、試してみる価値はあると思います。

于 2011-09-16T21:31:28.913 に答える