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>文档中有关 Thread Safey 的说明。

忽略那个。我误解了文档的上下文。您的代码很好,并且确实是线程安全的。感谢 Jim 和 Alexi 澄清了这一点。

于 2013-09-05T21:51:35.243 回答
1

它们可以被“信任”,但这并不意味着它们会非常准确。

这取决于很多因素,但基本上你会想要测量action()(在同一个线程上)的大量调用并将它们平均。特别是当单个呼叫需要相对较短的时间(<= 1 ms)时

您仍然需要处理外部因素,Windows 不是实时操作系统。

于 2013-09-05T21:40:36.563 回答