TheHorse1234
TheHorse1234

Reputation: 58

Thread Safe Method with a Stop Watch

I'm trying to determine if my code I'm using is Thread Safe or not. I'm basically trying to call a method several times from different threads, and capture the time it takes for certain calls within the method to complete.

Here is an example of what I am doing.

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();
        }
    }
}

}

And what I'm trying to determine is whether or not the TimeSpan values returned by the CaptureTime method can be trusted.

Thank you to anyone who can enlighten me.

Upvotes: 2

Views: 2023

Answers (2)

Matt Johnson-Pint
Matt Johnson-Pint

Reputation: 241693

Use of Stopwatch here is not the problem. See this recent answer. Since you are in a single thread when you use the Stopwatch, it will work fine.

But I'm not sure this approach is really going to be very useful. Are you trying to create your own profiler? Why not just use existing profiling tools?

When you spin up 50 instances of the same operation, they're bound to fight for the same CPU resources. Also, a new Task might or might not spin up a new thread. Even then, the amount of switching involved would make the results less-than-meaningful. Unless you are specifically trying to observe parallel behavior, I would avoid this approach.

The better way would be to run the action 50 times sequentially, time the whole thing, then divide by 50. (Assuming this is a short-running task.)

The using of BlockingCollection<TimeSpan>(new ConcurrentBag<TimeSpan>()) is also very weird. Since you are just adding to the list, and it is static and pre-created, then you can just use List<TimeSpan>. See the notes on Thread Saftey in the List<T> documentation here.

Ignore that. I misunderstood the context of the docs. Your code is just fine, and is indeed thread-safe. Thanks to Jim and Alexi for clearing that up.

Upvotes: 3

Henk Holterman
Henk Holterman

Reputation: 273449

They can be 'trusted' alright but that does not mean they will be very accurate.

It depends on lots of factors but basically you would want to measure a large number of calls to action() (on the same thread) and average them. Especially when a single call takes a relatively short time ( <= 1 ms)

You will still have to deal with external factors, Windows is not a Real Time OS.

Upvotes: 1

Related Questions