3

私はしばらくの間、マルチスレッドの問題に取り組んできました。過去数日間、すべての呼び出しがスレッドセーフであることを確認しようと努めてきました。私はちょうど私を投げた問題に遭遇しました. シナリオは次のとおりです。

~500 ポイント/秒/波形が渡される Infragistics XamDataChart コントロールを使用して、波形をプロットしようとしています。アプリケーションの起動時に、WaveData という名前の ObservableCollection プロパティを持つオブジェクトを作成します。これらのプロパティは、items コントロールの xaml に直接バインドされます。データが受信されると、キューに格納され、生成されたワーカー スレッドを使用してデータがデキューされ、適切な位置でコレクションが更新されます。

スポーン ワーカー スレッド:

QueueProcessThread = Task.Factory.StartNew(() => UpdateWaveFormCollections(WaveForms), tokenSource.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);

ループで実行されるコレクションを更新するコード (簡潔にするために一部のコード行を省略):

waveForm.LastDisplayedTimeStamp = DateTime.Now; // move the last displayed time up

int collectionSize = waveForm.WaveData.Count; 
while (waveForm.WaveDataBuffer.Count > 0 && waveForm.WaveDataBuffer.Peek().TimeStamp < waveForm.LastDisplayedTimeStamp)
{
   if (waveForm.CurrentPosition >= collectionSize)
   {
      waveForm.CurrentPosition = 0;
   }
   waveForm.WaveData[waveForm.CurrentPosition] = waveForm.WaveDataBuffer.Dequeue();
   waveForm.CurrentPosition++;
}

ご覧のとおり、コレクションに対してアイテムを実際に追加/削除するのではなく、特定の位置でアイテムを更新するだけです。これは、病院の患者モニターのようにしたかったからです。

私が直面している問題は、このコレクションを非 UI スレッドで更新していて、そのコレクションが Infragistics LineSeries に直接バインドされていることに気付いたことです...そしてこれは機能しています。ただし、予想される非 UI スレッドでコレクションを更新すると、Infragistics StepLineSeries を使用する別のグラフで例外がスローされます。非 UI スレッドでバインドされたコレクションを更新するにはどうすればよいですか?1) UI 以外のスレッドではコレクションを更新できないというエラーが発生する場合があり、2) ディスパッチャを介して波形の更新を UI スレッドに切り替えると、GUI のパフォーマンスが非常に悪かったため、これが懸念されます。使用不可でした。なぜこれが機能するのかを理解する必要があるので、続行する方法を知っています。私は、自分のスレッドの管理ミスが原因でいつでも失敗する可能性のあるアプリケーションをデプロイしたくありません。非UIスレッドでバインドされたObservableCollectionを更新できる理由/方法を探しています。ヘルプ/提案をいただければ幸いです。

4

3 に答える 3

3

Maybe you need to look into using the Dispatcher (unless thats part of your code omitted).

You can use the Dispatcher method when you do an operation that will require code to be executed on the UI thread.

Maybe you could retrieve that data in the background worker thread and when you update your collection propagate changes back to the UI thread

e.g.

Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background,
  new Action(() => methodHere = 50));
于 2013-02-13T14:22:27.133 に答える
0

私が探していた答えは、データバインドされたオブジェクトのプロパティを更新でき、WPF がディスパッチを処理するということですが、非 UI スレッドからコレクションを更新 (追加/削除/クリア) することはできません。私の波形では、ポイントを追加するのではなく、特定のインデックスでアイテムの値を更新していました。ただし、他のシナリオでは、常にポイントを追加および削除していました。

于 2013-04-04T15:23:22.183 に答える