我正在尝试确定我使用的代码是否是线程安全。我基本上试图从不同的线程中多次调用一个方法,并捕获方法中某些调用完成所需的时间。
这是我正在做的一个例子。
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值是否可以信任。
感谢任何能够启发我的人。
答案 0 :(得分:3)
在这里使用Stopwatch
不是问题。见recent answer。由于您在使用秒表时处于单个线程中,因此它可以正常工作。
但我不确定这种方法真的会非常有用。你想创建自己的探查器吗?为什么不使用现有的分析工具?
当您启动相同操作的50个实例时,它们必然会争夺相同的CPU资源。此外,新Task
可能会或可能不会启动新线程。即便如此,所涉及的转换量也会使结果失去意义。除非你特意试图观察并行行为,否则我会避免这种做法。
更好的方法是按顺序运行动作50次,计算整个时间,然后除以50.(假设这是一个短期运行的任务。)
使用 BlockingCollection<TimeSpan>(new ConcurrentBag<TimeSpan>())
也很奇怪。由于您只是添加到列表中,并且它是静态的并且已预先创建,因此您只需使用List<TimeSpan>
即可。请参阅List<T>
文档here中有关Thread Saftey的说明。
忽略这一点。我误解了文档的背景。你的代码很好,而且确实是线程安全的。感谢Jim和Alexi清理它。
答案 1 :(得分:1)
他们可以“信任”好,但这并不意味着他们会非常准确。
这取决于很多因素,但基本上你想要测量大量对action()
的调用(在同一个线程上)并对它们进行平均。特别是当单个呼叫花费相对短的时间(<= 1ms)时,
您仍然需要处理外部因素,Windows不是实时操作系统。