1

私の .Net コンソール アプリには、シリアル ポートに少数のバイト (約 20) を書き込み、応答を読み取る次のメソッドがあります (これも 20 バイト以下です)。これは、外部ハードウェア デバイスとの通信 (データの要求を送信し、要求された値を取得する) に使用されます。

余分なコード、ポートの初期化、変数の宣言などを切り取りましたが、それが何をしているかを見ることができます:-

var sw = new Stopwatch();
sw.Start();

// Write the "request" bytes.
_port.Write(buffer, 0, buffer.Length);

Console.WriteLine("After write: {0}", sw.ElapsedMilliseconds);
sw.Restart();

// Wait for response, but timeout after 100ms.
var timeoutCount = 0;
while (_port.BytesToRead == 0 && timeoutCount < 100)
{
    Thread.Sleep(1);
    timeoutCount++;
}

Console.WriteLine("Waited: {0}, #loops: {1}", sw.ElapsedMilliseconds, timeoutCount);

if (_port.BytesToRead == 0)
{
    // Timed-out..
    return null;
}

// Read the response.
var receivedData = new byte[_port.BytesToRead];
_port.Read(receivedData, 0, receivedData.Length);

return receivedData;

私のアプリは、タイトな (ほぼ継続的な) ループで上記のコードを呼び出します。いくつかのタイミングを出力するためにいくつかの Console.WriteLines を追加したことに気付くでしょう。次のような非常に一貫した数値が表示されます。

After write: 0
Waited: 14, #loops: 1
After write: 0
Waited: 14, #loops: 1
After write: 0
Waited: 14, #loops: 1
...and so on...

while明らかに、書き込みは非常に迅速に行われており、アプリがループを 1 回しか通過しないため、応答も迅速に到着していますThread.Sleep(1)

PC で別のウィンドウを開いたり、Chrome を実行したり、マウスを動かしたりすると、次のような数値が表示されます。

After write: 0
Waited: 4, #loops: 5
After write: 0
Waited: 2, #loops: 3
After write: 0
Waited: 2, #loops: 3
After write: 0
Waited: 1, #loops: 2
After write: 0
Waited: 3, #loops: 4

これは、私のようなシリアル ポート コードから期待されるものに似ており、PC が「アイドル」のときに見られる謎の 14 ミリ秒ではありません。何が起こっているかについてのアイデアはありますか?

私のアプリは100ミリ秒ごとに約12回の書き込み/読み取りを実行する必要があるため、問題が発生しています。2 番目の一連のタイミング (それぞれ数ミリ秒) から、これは簡単に達成できることがわかりますが、PC が「アイドル」の場合、各書き込み/読み取りに 14 ミリ秒かかるため、アプリで定期的にデータが失われます (これは外部で更新されます)。デバイスごとに 100 ミリ秒)。

4

1 に答える 1

0

リアルタイムの要件があるようですが、非リアルタイム システム (Windows) で開発しています。Sleep(1) は、スレッドを少なくとも 1 ミリ秒の間再アクティブ化できないことを OS に通知するだけなので、スレッドは最低 1 ミリ秒の間消え、スケジューラが到達すると元に戻ります。

マウスの動きによって動作が改善されるように見える理由は、すべてのマウス移動イベントによってスケジューラがより頻繁に呼び出されるためです。

_port.write() が WaitForSingleObject や Sleep などのシステム コールでブロックされている場合は難しいかもしれませんが、リアルタイム OS の使用を検討するか、スケジューリングにウィンドウに依存しないでください。また、リアルタイム要件をすべて削除して、シリアルポートから取得したものを取得するたびに取得することも検討できます。

于 2012-10-01T11:58:42.297 に答える