2

この質問には特定のシナリオがありますが、一般的な解決策は多くの状況に適用できるはずです。

アイテムの IsSelected プロパティがビュー モデルの対応するプロパティにデータ バインドされている WPF ItemsControl があります。次に、選択された項目に対して (バックグラウンド スレッドで) 実行される計算集約型のルーチンがあります。問題は、アイテムの IsSelected プロパティへの変更で計算集約型タスクをトリガーすると、複数のアイテムが一度に選択されたときに、計算集約型タスクが選択されたアイテムごとに 1 回実行されることです。アイテムが選択されており、それが必要なすべてであるため、実際に必要なよりもはるかに多くのプロセッサ時間がかかることになります。

IEnumerable<MyObject> items;

...

void IsSelectedPropertyChangedListener(object sender, PropertyChangedEventArgs e)
{
    if(e.PropertyName == "IsSelected")
        DoSomeIntensiveCalculation(items.Where(t=>t.IsSelected));
}

void DoSomeIntensiveCalculation(IEnumerable<MyObject> itemsToCalculate)
{
    ...
}

もちろん、ItemsControl の SelectionChanged イベントを登録し、それをトリガーすることもできます。これは、複数の項目が選択されている場合でも、選択の変更ごとに 1 回しか呼び出されないためです。に適用できますが、そのような簡単な回避策はありません。(この特定の状況でなぜこのようにするべきかについての良い議論があれば、それはどの代替案よりも優れているので、私は喜んで耳を傾けます)

私が考えることができる別の例は、おそらく ObservableCollection があり、それが変更されるたびに何か難しいことを計算したいということです。当然のことながら、CollectionChanged イベントを登録して計算をトリガーしますが、何かが一度に多数の項目をコレクションに追加するとします。追加される各アイテムは、パフォーマンスを大幅に低下させます。

別のインスタンスがすでに実行を開始している場合、集中的なタスクの実行をブロックできます。終了時にもう一度実行するようにフラグを設定するだけです。これにより、多数のものが一度に選択された場合でも、2 回しか実行されなくなります。 、しかし、それは実際に必要なよりも 1 倍多いです。

新しいタスクが開始されるたびに、既に実行中のタスクのインスタンスを強制終了できますが、これには、要求されたときに正常に停止するために、計算タスクに多くのコードを追加する必要があります。また、集中的なタスクが制御できない状況 (つまり、サードパーティのライブラリにあり、適切な停止メカニズムが提供されていない) では機能しません。

4

1 に答える 1

0

あなたが何を求めているのか100%確信が持てませんが、ここにいくつかのアイデアがあります:

  1. タスク並列ライブラリを使用します。タスク マネージャーは、スレッドを起動するかどうかを決定します。
  2. ブロッキング キューを使用します。
  3. インターフェースを再設計して計算ボタンを追加
  4. 最初の計算の後に結果をキャッシュします。
于 2013-09-18T14:09:20.247 に答える