はじめに: モーション トラッカーを使用して人間の運動系を分析するソフトウェアを開発しています。現在、xsens からハードウェアを実装し、SDK を使用してワイヤレス センサーからデータを受信しています。SDK は、現在利用可能な xyz 軸データ (簡略化) を受け取るために呼び出す「getData」メソッドを備えた COM インターフェイスを提供します。getData を呼び出さない場合、その「ビート」をスキップするため、データが失われ、ハードウェア/SDK にキャッシュがありません。
問題: 私の問題は、少なくとも 75Hz、できればもう少し高い速度でデータを取得する必要があることですが、75 は許容範囲ですが、現在、1 秒あたりわずか 20 信号に急速に低下しています... 処理を削除するとビット (以下のサンプルを参照) 完璧なサンプル レートが得られたので、デキューが原因でエンキューが一時停止していると思います。または、「重い」CPU 負荷が原因で、すべてのスレッドが待機しています。実際に何が原因なのかを突き止める方法がわかりません。プロファイラー (EQATEC) は、しばらくすると「GetData」メソッドに時間がかかっていることを示しているだけです。
質問: これを達成するために使用する最適な手法は何ですか? 「読み取り」スレッドが中断/ブロックされるのはなぜですか? 途中で中断せずに読みたいという方も多いのではないかと思いますが、ググって2週間経ちましたが、どうやら正しい単語が見つからないみたいです。
お知らせ下さい。
ありがとう
MultiMedia タイマー ( http://www.codeproject.com/Articles/5501/The-Multimedia-Timer-for-the-NET-Framework ) と BackgroundWorkerを使用した簡略化されたコード サンプル、バージョン 4
public class Sample
{
private MultiMediaTimer _backgroundGetData;
private bool _backgroundGettingData;
private BackgroundWorker _backgroundProcessData;
private ConcurrentQueue<double> _acceleration = new ConcurrentQueue<double>();
private void StartProcess()
{
if (_backgroundGetData == null)
{
_backgroundGetData = new MultiMediaTimer {Period = 10, Resolution = 1, Mode = TimerMode.Periodic, SynchronizingObject = this};
_backgroundGetData.Tick += BackgroundGetDataOnTick;
}
_backgroundProcessData = new BackgroundWorker {WorkerReportsProgress = false, WorkerSupportsCancellation = true};
_backgroundProcessData.DoWork += BackgroundProcessDataOnDoWork;
_backgroundGetData.Start();
}
private void BackgroundProcessDataOnDoWork(object sender, DoWorkEventArgs doWorkEventArgs)
{
double value;
if (!_acceleration.TryDequeue(out value)) value = 0;
//Do a lot of work with the values collected so far,
//this will take some time and I suspect it's the cause of the delays?
}
private void BackgroundGetDataOnTick(object sender, EventArgs eventArgs)
{
if (_backgroundGettingData) return;
_backgroundGettingData = true;
//123 represents a value I am reading from the sensors using the SDK
double value = 123;
if (value == -1)
{
Thread.Sleep(5);
continue;
}
_acceleration.Enqueue(value);
if (_acceleration.Count < 5) continue;
if (!_backgroundProcessData.IsBusy)
{
_backgroundProcessData.RunWorkerAsync();
}
_backgroundGettingData = false;
}
}