2

使用しているコードがスレッド セーフかどうかを判断しようとしています。私は基本的に、異なるスレッドからメソッドを数回呼び出し、メソッド内の特定の呼び出しが完了するまでにかかる時間をキャプチャしようとしています。

これが私がやっていることの例です。

using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;

namespace ThreadTest
{
class Program
{
    static BlockingCollection<TimeSpan> Timer1 = new BlockingCollection<TimeSpan>(new ConcurrentBag<TimeSpan>());

    static TimeSpan CaptureTime(Action action)
    {
        Stopwatch stopwatch = Stopwatch.StartNew();
        action();
        stopwatch.Stop();
        return stopwatch.Elapsed;
    }

    static void ThreadFunction()
    {
        TimeSpan timer1 = new TimeSpan();
        timer1 = CaptureTime(() =>
            {
                //Do Some Work
            });
        Timer1.Add(timer1);
    }

    static void Main(string[] args)
    {
        for (int i = 0; i < 50; i++)
        {
            var task = new Task(ThreadFunction);
            task.Start();
        }
    }
}

}

そして、私が判断しようとしているのは、CaptureTime メソッドによって返される TimeSpan 値が信頼できるかどうかです。

私を啓発できる人に感謝します。

4

2 に答える 2

3

Stopwatchこちらの使用は問題ありません。この最近の回答を参照してください。ストップウォッチを使用するときはシングル スレッドであるため、問題なく動作します。

しかし、このアプローチが本当に役立つかどうかはわかりません。独自のプロファイラーを作成しようとしていますか? なぜ既存のプロファイリング ツールを使用しないのでしょうか?

同じ操作のインスタンスを 50 回起動すると、それらは同じ CPU リソースを奪い合うことになります。また、Task新しいスレッドが新しいスレッドを起動する場合としない場合があります。それでも、関連する切り替えの量により、結果は意味をなさないものになります。特に並列動作を観察しようとしている場合を除き、このアプローチは避けます。

より良い方法は、アクションを 50 回連続して実行し、全体の時間を計測してから 50 で割ることです (これが実行時間の短いタスクであると仮定します)。

の使用BlockingCollection<TimeSpan>(new ConcurrentBag<TimeSpan>())も非常に奇妙です。リストに追加するだけで、静的で事前に作成されているので、そのまま使用できますList<TimeSpan>List<T>ドキュメントのスレッド セーフティに関する注意事項は、こちら を参照してください

それは無視してください。ドキュメントの文脈を誤解しました。あなたのコードは問題なく、実際にスレッドセーフです。解決してくれた Jim と Alexi に感謝します。

于 2013-09-05T21:51:35.243 に答える
1

それらは問題なく「信頼」できますが、それはそれらが非常に正確であるという意味ではありません.

多くの要因に依存しますが、基本的には、(同じスレッドで) への多数の呼び出しを測定し、action()それらを平均する必要があります。特に、1 回の呼び出しにかかる時間が比較的短い場合 (<= 1 ミリ秒)

Windows はリアルタイム OS ではありません。

于 2013-09-05T21:40:36.563 に答える