ほとんどのプロパティを持つオブジェクトを非常に軽量にします - テキストは最大 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;
}