1

私は報告システムに取り組んでおりDocumentPageDocumentPaginator. これらのドキュメントには、インスタンス化される多くのWPF コンポーネントXpsDocumentWriterが含まれているため、ページネーターは、後で(実際のプリンターに送信されます) に送信されるときに正しいものを含めます。

私の問題は、インスタンスの作成にかなりの時間がかかることです(Windowsがアプリケーションを凍結としてマークするのに十分です)ので、バックグラウンドスレッドDocumentPageでインスタンスを作成しようとしました.WPFはそれらの属性がGUI スレッド。また、これまでに作成されたページ数を示すプログレス バーを表示したいと考えています。したがって、GUI上で2つのことを並行して起こそうとしているようです。

この問題は説明が難しく、どのように対処すればよいか本当にわかりません。要するに:

  • 一連のDocumentPage を作成します。
    • これらにはWPF コンポーネントが含まれます
    • これらはバックグラウンド スレッドで作成するか、アプリケーションがフリーズしないように他のトリックを使用します。
  • 各ページが作成された後、WPF ProgressBarを更新する必要があります。

これを行う適切な方法がない場合は、代替のソリューションとアプローチを歓迎します。

4

5 に答える 5

1

スレッドがSTAである限り、バックグラウンドスレッドでパジネーターを実行できるはずです。

スレッドを設定したら、実行する前にこれを試してください。

thread.SetApartmentState(ApartmentState.STA);

本当にGUIスレッドを使用する必要がある場合は、オブジェクトをバックグラウンドスレッドからGUIスレッドに移動する必要がある可能性があるため、 Freezableクラスを確認してください。

于 2010-06-10T20:54:22.480 に答える
0

これについてはゲームに少し遅れていますが、これに対する解決策を見つけたので、共有したいと思いました. UI 要素を表示するには、表示される UI スレッドで作成する必要があります。長時間実行されるタスクは UI スレッド上にあるため、進行状況バーが更新されなくなります。これを回避するために、新しい UI スレッドでプログレス バーを作成し、メイン UI スレッドでページを作成しました。

        Thread t = new Thread(() =>
            {
                ProgressDialog pd = new ProgressDialog(context);
                pd.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterScreen;
                pd.Show();
                System.Windows.Threading.Dispatcher.Run();
            });
        t.SetApartmentState(ApartmentState.STA);
        t.IsBackground = true;
        t.Start();

        Action();   //we need to execute the action on the main thread so that UI elements created by the action can later be displayed in the main UI

「ProgressDialog」は、進行状況情報を表示するための独自の WPF ウィンドウでした。

「コンテキスト」には、進行状況ダイアログの進行状況データが保持されます。メインスレッドで実行中のアクションを中止できるように、キャンセルされたプロパティが含まれています。また、アクションが完了したときに進行状況ダイアログを閉じることができるように、完全なプロパティも含まれています。

「アクション」は、すべての UI 要素を作成するために使用されるメソッドです。キャンセル フラグのコンテキストを監視し、フラグが設定されている場合は UI 要素の生成を停止します。完了すると、完了フラグが設定されます。

Thread 't' を STA スレッドに設定し、IsBackground を true に設定しなければならなかった正確な理由は覚えていませんが、これらがないと機能しないことは確かです。

于 2013-12-09T18:22:59.593 に答える
0

Ray Burns の回答をさらに詳しく説明します。データ処理をバックグラウンド スレッドのクラスで実行し、処理が完了したら DocumentPage のプロパティをこのクラスにデータバインドできませんでしたか?

于 2010-08-06T12:27:26.860 に答える
0

私の推測では、作成に時間がかかるものはすべてビジュアル内にあると思います。その場合、簡単な解決策があります。DocumentPaginator.GetPage() が呼び出されるまで、実際の DocumentPage オブジェクトとそれに関連付けられた Visual を作成しないでください。

ドキュメントを使用するコードが一度に 1 ページまたは 2 ページしか要求しない限り、パフォーマンスのボトルネックは発生しません。

プリンターまたはファイルに印刷する場合は、すべてバックグラウンド スレッドで実行できますが、画面に表示する場合は、一度にいくつかの DocumentPages を表示するだけで済みます。どちらの場合も、UI のロックアップは発生しません。

最悪のシナリオは、サムネイル ビューでページを表示するアプリです。この場合、次のようにします。

  1. サムネイル ビューは、ItemsSource を "RealizedPages" コレクションにバインドします。このコレクションは、最初はダミー ページで満たされています。
  2. ダミー ページが測定されるたびに、DispatcherPriority.Background でディスパッチャ操作をキューに入れ、DocumentPaginator.GetPage() を呼び出してから、RealizedPages コレクション内のダミー ページを実際のページに置き換えます。

個別のアイテムの数が原因で 1 つのページを実現してもパフォーマンス上の懸念がある場合は、ページ上の ItemsControl に多数のアイテムがある場合でも、この同じ一般的なアプローチを使用できます

もう 1 つ注意: XPS 印刷システムは、一度に複数の DocumentPage を処理することはありません。そのため、それがクライアントであることがわかっている場合は、実際には、適切な変更を加えて同じ DocumentPage を何度も返すことができます。

于 2010-06-12T00:59:23.703 に答える
0

UI スレッドを必要とする部分が比較的小さい場合は、Dispatcherを使用して、UI をブロックせずにそれらの操作を実行できます。これにはオーバーヘッドが伴いますが、バックグラウンドで大量の計算が行われる可能性があり、UI スレッドでの作業が他の UI タスクとインターリーブされる可能性があります。Dispatcher を使用して進行状況バーを更新することもできます。

于 2010-06-10T21:10:43.497 に答える