0

私は自分の状況を説明します。

私はプロデューサ1からNコンシューマパターンを持っています。ブロッキング コレクションを使用していますが、すべて正常に動作しています。いくつかのテストを行って、この奇妙な動作に気付きました:

私は、消費者のデータ操作にかかる時間をテストしていました。この奇妙なことに気付きました。以下に、私の操作が削除され、奇妙な動作を引き起こすコードが表示されます。

1 つのプロデューサーに対して 4 つのコンシューマーがあります。ほとんどのデータについて、コンソールは何も出力しません。これは ts=0 (目盛りの下) であるためですが、ランダムに (1 から 5 秒ごとに) 次のようなものをプロットします (この非常に特定の順序ではなく、同じ種類の) ):

10000
20001
10000
30002
10000
40003
10000
10000

約 10,000 ティックなので、約 1 ミリ秒です。常に (N)000(N-1) の形式の数値です。使用する BlockingCollection は、完全にランダムな時間に発生したいくつかのネットワーク イベントに応じて満たされることに注意してください。ここから通常のものはありません。

タイミングはほぼ完璧で、常に 10,000 ティックの倍数です。

この背後には何がありますか? ありがとう!

    while(IsAlive)
    {
            DataToFieldMapping item;
            try
            {
                _CollectionToConsume.TryTake(out item, -1);
            }
            catch
            {
                item = null;
            }
            if (item != null)
            {
                    long ts = (DateTime.Now.Ticks - item.TimeStamp.Ticks);
                    if(ts>10)
                       Console.WriteLine(ts);
            }
     }
4

2 に答える 2

4

ここで起こっていることDateTime.Nowは、精度がかなり制限されているということです。それはあなたに最も近い目盛りまでの時間を与えていません。約 10,000 ティックごとにのみ更新されるため、通常、プリントに 10,000 ティックの倍数が表示されます。

これらのイベントの期間をより正確に把握したい場合は、はるかに高い精度StopWatchを持つクラスを使用してください。とはいえ、これは単なる診断ツールです (そのため、名前空間にあるのです)。何が起こっているのかを診断するためにのみ使用し、本番コードで使用する必要があります。StopWatchDiagnostics

余談ですが、ここでタイマーを使用する必要はまったくありません。BlockingCollection新しいコンテンツをポーリングしている複数のコンシューマーを作成しているようです。これを行う理由はありません。コレクションにアイテムが含まれるまで、単純にブロックできます。(したがって、名前、BlockingCollection.

最も簡単な方法は、消費者が単純にこれを行うことです。

foreach(var item in _CollectionToConsume.GetConsumingEnumerable())
   ProcessItem(item);

次に、そのコードをバックグラウンド スレッドで実行します。

于 2014-03-07T19:28:52.980 に答える
1

次のように記述して実行すると、ティックが 1 対 1 でロールするのではなく、比較的大きなチャンクで b/c ティックの解像度が実際にははるかに小さいことがわかります。

for(int i =0; i< 100; i++)
{
    Console.WriteLine(DateTime.Now.Ticks);
}

クラスを使用Stopwatchしてパフォーマンスを測定します。これは、目的により適した高解像度タイマーを使用するためです。

于 2014-03-07T19:31:13.257 に答える