0

I have a queue of tasks that are processed by a number of different threads. I want the threads that are doing the task processing to process until the task queue is empty or until a certain amount of time (say 5000 milliseconds) have passed.

I'm wondering what's a reliable way to determine the amount of time that has passed across threads in c#?

Ideally I'd use something like StopWatch but it seems like that might not be threadsafe...

Is there some better alternative thing that I can use to calculate time elapsed from a single point from multiple different threads?

I want to write code that looks something like this:

Stopwatch stopwatch = new Stopwatch();
CountdownEvent runningProcessors = new CountdownEvent(0);

// Main thread starts processing on threadpool threads, and itself
void SpawnProcessors() {
    runningProcessors(1);
    stopwatch.Reset();
    stopwatch.Start();

    for (int i = 0; i < chosenNumberOfThreads; i++)
    {
        // process on threads
        pendingJobs.AddCount();
        ThreadPool.QueueUserWorkItem(_ => ProcessQueue());
    }

    // also process on the main thread
    ProcessQueue();

    // wait for all processing to finish
    pendingJobs.Wait();

    stopwatch.Stop();
}

// Method run by processing threads
void ProcessQueue() {
    while (workQueue.Count > 0 && stopwatch.ElapsedMilliseconds < 5000) {
        workQueue.Dequeue().DoWork();
    }
    pendingJobs.Signal();
}
nbarrash
  • 1
  • 2
  • 1
    Search for "Cancellation in Managed Threads", "CancellationToken", a bit older "ManualResetEvent ", declare Stopwatch in SpawnProcessors(), instead of calling ProcessQueue(); check elapsed time there and do the cancellation/signalling there. – A.J.Bauer Nov 20 '21 at 05:47
  • What is the type of the `workQueue` variable? Also are you trying to implement a rate-limiting functionality, like the one requested [here](https://stackoverflow.com/questions/65825673/partition-how-to-add-a-wait-after-every-partition), or you want to [limit the concurrency](https://stackoverflow.com/questions/10806951/how-to-limit-the-amount-of-concurrent-async-i-o-operations) of asynchronous operations? – Theodor Zoulias Nov 20 '21 at 09:15
  • Main thread shouldn't process jobs; its task is to maintain schedule – Caius Jard Nov 20 '21 at 09:54
  • @TheodorZoulias let's say `ConcurrentQueue` – nbarrash Nov 20 '21 at 19:50
  • In that case you could consider using the [`ConcurrentQueue.TryDequeue`](https://learn.microsoft.com/en-us/dotnet/api/system.collections.concurrent.concurrentqueue-1.trydequeue?view=net-6.0) method, because the combination `Count`+`Dequeue` introduces a race condition. – Theodor Zoulias Nov 20 '21 at 19:52
  • Sure that's actually what I'm using in my code (I don't think it actually exposes a "Dequeue"), maybe I got too cute by simplifying it. I'm definitely not trying to rate limit. This is for a video game. I want to dedicate a certain amount of time each frame to some "work" and then stop working, _roughly_ after a certain point. Ideally all CPU cores (which can vary depending on the player) would be engaged, including the main thread. I know thread =/= cpu core necessarily, just looking for a good way to usually ensure that all CPU cores are engaged. Edit: oops I see the race condition. – nbarrash Nov 20 '21 at 20:00

0 Answers0