4

難問があります。私は非常にひどく設計された非常に複雑なシステムを「継承」しており、それを(チームとともに)1つずつ近代化および再構築しています。問題は、現在のシステムが200人以上のユーザーに依存しており、設計(の欠如)が原因でパフォーマンスに大きな問題が発生していることです。現時点で最も問題となる問題は、UIスレッドにかなりの量の作業が行われていることです。これにより、スレッドがクリアされるまでGUIがハングし、メッセージのポンピングを続行できます。他のスレッドでの他の計算結果のためにグリッド内の多数のフィールドを更新しているため、この作業の多くは実際にはGUIスレッドで行う必要があります。

問題はこれです:ここに含まれるスレッドモデルと基礎となるクラスを書き直すことに専念するためのリソースがありません。その作業の複雑さは、クライアントに受け入れられない重大なリスクをもたらします。

currnetスレッドモデルにあまり干渉せずに、UIのパフォーマンスを向上させる方法について誰かが提案を持っているかどうかを知りたいと思いました。

私の最初の考えは、GUIが過負荷にならないようにするため、またはGUIへのディスパッチをバックオフするときに、UIスレッドへの実際の呼び出しの前に「バッファー」を配置する方法があるかもしれないということです。

任意の提案をいただければ幸いです。

これが理想的ではないことはわかっていますが、私たちは今いる場所にいます。1年間の書き直しが完了する前に、ユーザーにより良いエクスペリエンスを提供したいと思っています。

ありがとう!

アップデート#1 これはwinformsアプリです...申し訳ありませんが、これは最初は明確ではありませんでした。新しいコードはWPFですが、これらのモジュールはWinFormsです。

アップデート#2 最初は、UIスレッドへのほとんどのBeginInvoke呼び出しをInvokeに変更して、UIの応答性を向上させるシリアル化を導入しようと考えています。ここで、誰もが予測できる(明らかではない)欠点はありますか?

4

3 に答える 3

1

あなたの特定のケースでそれが機能するかどうかはわかりませんが、私は過去に同様の(おそらくストレスは少ないですが)状況にあり、多かれ少なかれ恣意的にマーシャリングできるコードを思いつきましたバックグラウンドスレッドからUIスレッドへのコード。これは、WinFormsの時代に書かれました。

これにより、一部のバックグラウンドスレッドで計算をスローバックし、スレッドモデルを完全に再構築する(またはその欠如)ことなく、UIの更新をより簡単にフォアグラウンドにマーシャリングするためのリスクの低い手法が提供される場合があります。

UIのパフォーマンスに関しては、UIを高速化するための最良の方法は、実行回数を減らすことです。リンクされたコードを作成したときに作業していたアプリケーションは、数百メガバイトの文字列を解析して、いくつかのxmlを手動で変更していました。不変の文字列を文字列ビルダーに置き換えると、操作はOOM障害状態から実時間の5分以内に完了しました。次に、解析したすべての要素について、UIが更新されていることに気付きました。そのコードを微調整して、50要素程度ごとにUIを更新しました。これにより、わずか1分でUIが更新されました。すべてのUI更新をオフにすると、時間が数秒に短縮されました。

計算が完了するまでUIを更新しないことを検討しましたか?おそらく、代わりにプログレスバーを実行するだけですか?もう1つの可能性(頭のてっぺんから、それがどれほど邪悪かはわかりません)は、更新されるコントロールからキーオフされた辞書のラムダとして更新をキューに入れることです。そうすれば、1つのコントロールが複数回更新された場合に、冗長な更新を値に置き換えることができます。たとえば、(これは、アプリが計算を実行するためにUIから直接値を読み取っていないことを前提としています。おそらくそうです。:()

于 2011-04-28T20:09:38.313 に答える
0

これがWinFormsアプリケーションであると仮定すると、かなりハックなアプローチの1つは、UIスレッドで実行されている集中的な作業内で定期的にApplication.DoEvents()を呼び出すことです。これにより、メッセージポンプはロジックの途中で保留中のメッセージを処理できます。これには、次のような独自の危険が伴うことに注意してください。

  1. すべてのUIイベントが発生する可能性があります。つまり、ボタンを押すと長時間実行されるUI更新がトリガーされ、その後DoEvents()で生成された以前のUI作業がブロックされます。これの特に陰湿な形は、ボタンを「ダブルクリック」すると、長い操作がスピンアップし、DoEvents()になります。これは、別のボタンクリックを処理し、完了まで実行されてから制御を返す同じ操作をスピンアップします。操作の途中で最初のボタンクリックハンドラーに戻ります。これが意味することは、UIスレッドでのこれらの「長時間実行」操作中に許可するUIインタラクションに非常に注意する必要があるということです。

  2. ユーザーはUIを操作できるため、コードが変更されていないことについて以前に行った仮定を無効にする可能性があります。繰り返しになりますが、操作が依存する状態を無効にできないように、ユーザーが実行できることを制限することが重要です。もちろん、別のスレッドで実行されているコードでも同じ問題が発生します。

  3. これは、VB6(マルチスレッドを実行するのが非常に困難であった)の時代にはかなり一般的な手法でしたが、最近の開発では嫌われています。レガシーアプリケーションの狭い場所から抜け出すことができるかもしれませんが、//HACK将来のクリーンアップのためにタグでフラグを立てることをお勧めします。

于 2011-04-28T20:26:15.957 に答える
0

大規模な更新を行う場合は、 CurrencyManagerのSuspendBindingメソッドとResumeBindingメソッドを使用して、コントロールのバインディングを一時停止および再開できます。このように、UIの操作量が多いために別のスレッドで何かを移動できなかった場合でも、更新を表示しないことでパフォーマンスをいくらか向上させることができます。また、特にグリッドやその他のコントロールを使用している場合は、更新の最後までリスト変更通知を一時停止すると役立つ場合があります。

于 2011-04-28T20:19:07.063 に答える