2011-09-16 16 views
1

プロパティのほとんどが非常に軽量なオブジェクトを用意してください。テキストは200文字までです。 1つのプロパティはFlowDocumentで、大きくて非同期で取得することができます。 Async = Trueと設定した場合、「呼び出しスレッドは別のスレッドが所有しているため、このオブジェクトにアクセスできません。WPFバインドIsAsyncが失敗しました

<FlowDocumentReader Name="FlowDocumentPageViewer1" HorizontalAlignment="Stretch" 
     Document="{Binding Source={x:Static Application.Current}, Path=MyGabeLib.Search.SelectedDoc.DocFlowDocument, Mode=OneWay, IsAsync=True}" /> 

生産が取得はより複雑でさえ、単純なハードコードされたFlowDocumentとIsAsyc真で同じ失敗です。

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は3MBになり、他のすべてのプロパティ10Kを組み合わせるとパフォーマンスが大幅に向上し、最も使用されるボタンは次のオブジェクトになります。 FlowDocumentはSQLのvarchar(max)から来て、改行と強調表示された単語でフォーマットされます。それだけではありません - 他のプロパティに比べても高価です。

FlowDocumentReader自体は、大きなドキュメントでは最初のページを高速化してページを約100 /秒でロードするため、非同期でサポートされているようです。しかし、私はまだ他のすべてのプロパティが取得された後に1ページ目を取得したいと思います。

問題は、「FlowDocumentがディスパッチャオブジェクトであるため、作成したスレッドからしかアクセスできません」というmartinの問題がありました。

解決方法は、XAML文字列にシリアル化することでした。

public string XAMLdocFlowDocument 
    { 
     get 
     { 
      Thread.Sleep(6000); 
      return XamlWriter.Save(FlowDocumentSlow); 
     } 
    } 

プロパティがあるとき、私はFlowDocumentが作成されていることを推測(およびロード)していたコードを見ずに、コンバータ

<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

この場合、FallbackValueとは何ですか?これはバインディングで指定する必要があります(async opの処理中に適用される可能性があります)。 – Ricibob

+0

FallbackValueで失敗します。私がPriorityBindingを行うと、非同期ではなくなり、async getを呼び出してもXMALでは失敗します。 – Paparazzi

+0

なぜdownvote?明確ではない、研究の欠如を示す、または有用でないものは何ですか? – Paparazzi

答えて

2

の文字列にバインド読む。これは、プロパティのバインディングが非同期であるため、バックグラウンドスレッドで行われます。

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

したがって、作成したFlowDocumentにはUIスレッドからアクセスできません。

ドキュメントを非同期に読み込む別の方法が必要です。

おそらく、同期(通常)バインディングを使用してXamlReader.LoadAsyncを使用してドキュメントを読み込むことができますか?私は自分でそれを試していないが、私はそれを実験する価値があると推測している。

+0

私は質問にgetを追加しました。興味深いのはgetを呼び出し、getはエラーなしでflowdocumentを返します。 UIがバインドしようとすると失敗します。 getの呼び出しが適切なUIスレッド上にあるはずです。ドキュメントによると、IsAsync = Trueを追加するだけで、通常の非同期呼び出しを得ることができます。私はあなたのお勧めを見ていきますが、正直言って私はそれを完全に理解していません。 – Paparazzi

+0

get呼び出しは(別のスレッドで)非同期に行われます。問題は、getメソッドで新しいFlowDocumentインスタンスを作成していることです。そのインスタンスは正しく返されますが、別のスレッド(get呼び出しを行ったスレッド)によって作成されているため、UIスレッドで使用することはできません。そのため、UIが返されたFlowDocumentインスタンスを「使用する」まで、エラーは発生しません。 –

+0

UIスレッドでFlowDocumentインスタンスを作成する必要があります。ですから、それを非同期的にロードする方法が問題です。 –