I need to process data in another thread. It can be done in two ways:
Using a thread loop waiting for an event:
AutoResetEvent e = new AutoResetEvent(false)
Thread t = new Thread(delegate
{
while(true)
{
e.WaitOne();
// process data
}
};)
void OnProgramStarted() // one time
{
t.Start();
}
void OnDataReceived()
{
// put data to queue
e.Set();
}
Using the thread pool:
void ProcessData(object state)
{
// process data
}
void OnDataReceived()
{
// put data to queue
ThreadPool.QueueUserWorkItem(ProcessData);
}
What way will be faster?
The real tests give ambiguous results.
My benchmarking code:
using System;
using System.Diagnostics;
using System.Threading;
namespace t_event_tpool
{
class Program
{
const int t = 1000000;
static Stopwatch sw = new Stopwatch();
static int q1, q2;
static AutoResetEvent e1 = new AutoResetEvent(false);
static AutoResetEvent done1 = new AutoResetEvent(false);
static Thread thread = new Thread(ThreadProc);
static void ThreadProc(object state)
{
while(true)
{
e1.WaitOne();
q1++;
done1.Set();
}
}
static AutoResetEvent done2 = new AutoResetEvent(false);
static void PoolProc(object state)
{
q2++;
done2.Set();
}
static void TestA()
{
sw.Restart();
for(int i = 0; i < t; i++)
{
e1.Set();
done1.WaitOne();
}
sw.Stop();
Console.WriteLine("a " + sw.ElapsedMilliseconds + "\t" + q1);
}
static void TestB()
{
sw.Restart();
for(int i = 0; i < t; i++)
{
ThreadPool.QueueUserWorkItem(PoolProc, i);
done2.WaitOne();
}
sw.Stop();
Console.WriteLine("b " + sw.ElapsedMilliseconds + "\t" + q2);
}
static void Main(string[] args)
{
thread.IsBackground = true;
thread.Start();
TestA();
TestB();
TestA();
TestB();
TestA();
TestB();
}
}
}
On low CPU load (without other applications) TestB is 2 times faster than TestA. On high CPU load by other processes TestA faster than TestB.
You are testing the overhead of starting work. This is meaningless for the speed of the actual work. Rather than optimizing overhead, make your work-items more granular so that overhead does not matter. If your work-items run faster than 0.1ms I'd seriously consider making them bigger. In your test, your work-items take just a few instructions.
To answer the question: Your custom thread that is ready to run at the signal of an event has less overhead than posting a work item to the thread-pool. You are doing almost nothing. Hard to improve on that. You'd need to use high-speed queueing patterns like the Disruptor pattern.
Related
I'm looking for a fast way to let many worker threads wait for an event to continue and block the main thread until all worker threads are finished. I first used TPL or AutoResetEvent but since my calculation isn't that expensive the overhead was way too much.
I found a pretty interesting article concerning this problem and got great results (using only one worker thread) with the last synchronization solution (Interlocked.CompareExchange). But I don't know how to utilize it for a scenario where many threads wait for one main tread repeatedly.
Here is an example using single thread, CompareExchange, and Barrier:
static void Main(string[] args)
{
int cnt = 1000000;
var stopwatch = new Stopwatch();
stopwatch.Start();
for (int i = 0; i < cnt; i++) { }
Console.WriteLine($"Single thread: {stopwatch.Elapsed.TotalSeconds}s");
var run = true;
Task task;
stopwatch.Restart();
int interlock = 0;
task = Task.Run(() =>
{
while (run)
{
while (Interlocked.CompareExchange(ref interlock, 0, 1) != 1) { Thread.Sleep(0); }
interlock = 2;
}
Console.WriteLine($"CompareExchange synced: {stopwatch.Elapsed.TotalSeconds}s");
});
for (int i = 0; i < cnt; i++)
{
interlock = 1;
while (Interlocked.CompareExchange(ref interlock, 0, 2) != 2) { Thread.Sleep(0); }
}
run = false;
interlock = 1;
task.Wait();
run = true;
var barrier = new Barrier(2);
stopwatch.Restart();
task = Task.Run(() =>
{
while (run) { barrier.SignalAndWait(); }
Console.WriteLine($"Barrier synced: {stopwatch.Elapsed.TotalSeconds}s");
});
for (int i = 0; i < cnt; i++) { barrier.SignalAndWait(); }
Thread.Sleep(0);
run = false;
if (barrier.ParticipantsRemaining == 1) { barrier.SignalAndWait(); }
task.Wait();
Console.ReadKey();
}
Average results (in seconds) are:
Single thread: 0,002
CompareExchange: 0,4
Barrier: 1,7
As you can see Barriers' overhead seems to be arround 4 times higher! If someone can rebuild me the CompareExchange-scenario to work with multiple worker threads this would surely help, too!
Sure, 1 second overhead for a million calculations is pretty less! Actually it just interests me.
Edit:
System.Threading.Barrier seems to be the fastest solution for this scenario. For saving a double blocking (all workers ready for work, all workes finished) I used the following code for the best results:
while(work)
{
while (barrier.ParticipantsRemaining > 1) { Thread.Sleep(0); }
//Set work package
barrier.SignalAndWait()
}
It seems like you might want to use a Barrier to synchronise a number of workers with a main thread.
Here's a compilable example. Have a play with it, paying attention to when the output tells you that you can "Press <Return> to signal the workers to start".
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
namespace Demo
{
static class Program
{
static void Main()
{
print("Main thread is starting the workers.");
int numWorkers = 10;
var barrier = new Barrier(numWorkers + 1); // Workers + main (controlling) thread.
for (int i = 0; i < numWorkers; ++i)
{
int n = i; // Prevent modified closure.
Task.Run(() => worker(barrier, n));
}
while (true)
{
print("***************** Press <RETURN> to signal the workers to start");
Console.ReadLine();
print("Main thread is signalling all the workers to start.");
// This will wait for all the workers to issue their call to
// barrier.SignalAndWait() before it returns:
barrier.SignalAndWait();
// At this point, all workers AND the main thread are at the same point.
}
}
static void worker(Barrier barrier, int workerNumber)
{
int iter = 0;
while (true)
{
print($"Worker {workerNumber} on iteration {iter} is waiting for barrier.");
// This will wait for all the other workers AND the main thread
// to issue their call to barrier.SignalAndWait() before it returns:
barrier.SignalAndWait();
// At this point, all workers AND the main thread are at the same point.
int delay = randomDelayMilliseconds();
print($"Worker {workerNumber} got barrier, now sleeping for {delay}");
Thread.Sleep(delay);
print($"Worker {workerNumber} finished work for iteration {iter}.");
}
}
static void print(string message)
{
Console.WriteLine($"[{sw.ElapsedMilliseconds:00000}] {message}");
}
static int randomDelayMilliseconds()
{
lock (rng)
{
return rng.Next(10000) + 5000;
}
}
static Random rng = new Random();
static Stopwatch sw = Stopwatch.StartNew();
}
}
I have a application where multiple threads have to wait on an event to indicate that new data is available in a list. My expectation was that I could use an AutoResetEvent, WaitOne on it in each thread, and then when the data is available Set the event.
However, because it is auto reset the first thread clears the event and doesn't release the other threads. Now I could presumably make it a manual reset and implement a counter, but my feeling is that this is a common problem and so there must be a standard way to do it, but searching the docs I couldn't find one.
Any help? Here is some sample code that doesn't release all the threads:
static AutoResetEvent eve = new AutoResetEvent(false);
static void Main(string[] args)
{
var threads = new List<Thread>();
for (int i = 0; i < 10; ++i)
{
int iCopy = i;
var t = new Thread(() => thread(iCopy));
threads.Add(t);
t.Start();
}
Console.WriteLine("Pausing");
Thread.Sleep(5000);
eve.Set();
foreach (var t in threads) t.Join();
Console.WriteLine("All done");
Console.ReadKey();
}
static void thread(int n)
{
eve.WaitOne();
Console.WriteLine("Thread {0}", n);
}
Just use the ManualResetEvent in the place of AutoRestEvent. There is not need for counter. I tried , it worked below is the code.
static ManualResetEvent eve = new ManualResetEvent(false);
static void Main(string[] args)
{
var threads = new List<Thread>();
for (int i = 0; i < 10; ++i)
{
int iCopy = i;
var t = new Thread(() => thread(iCopy));
threads.Add(t);
t.Start();
}
Console.WriteLine("Pausing");
Thread.Sleep(5000);
eve.Set();
foreach (var t in threads) t.Join();
Console.WriteLine("All done");
Console.ReadKey();
}
static void thread(int n)
{
eve.WaitOne();
Console.WriteLine("Thread {0}", n);
}
I have a application where multiple threads have to wait on an event to indicate that new data is available in a list. My expectation was that I could use an AutoResetEvent, WaitOne on it in each thread, and then when the data is available Set the event.
You have a bit of a XY Problem, however thankfully you included what your "X" was (Make the threads get new data from a list once it is available).
Based off of your description I think you would be better off using a BlockingCollection, you can spin up as many threads as you want and they will all block till new data is available, as soon as data is available they unblock and take data till there is none left then re-block.
using System;
using System.Collections.Concurrent;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
static BlockingCollection<int> _items = new BlockingCollection<int>();
static void Main(string[] args)
{
//Start up 4 threads
var threads = new Thread[4];
for (int i = 0; i < threads.Length; i++)
{
var iCopy = i;
threads[i] = new Thread(() => ProcessItems(iCopy));
threads[i].IsBackground = true;
threads[i].Start();
}
//Give the threads 5 items to process.
for (int i = 0; i < 5; i++)
{
_items.Add(i);
}
Console.WriteLine("All items queued, sleeping 2 seconds");
Thread.Sleep(2000);
//Give the threads 10 more items to process.
for (int i = 0; i < 10; i++)
{
_items.Add(i);
}
_items.CompleteAdding();
Console.WriteLine("Marked adding complete");
foreach (var t in threads) t.Join();
Console.WriteLine("All threads complete");
Console.ReadLine();
}
static void ProcessItems(int i)
{
var rnd = new Random(i);
foreach (var item in _items.GetConsumingEnumerable())
{
Console.WriteLine("Thread {0} Processing item {1}", i, item);
//Simulate a random amount work
Thread.Sleep(rnd.Next(100, 500));
}
}
}
}
If you really want to release all the waiting threads just once, use an array of semaphores, one for each thread. When you want them all to go, send one unit to each semaphore in a loop.
I am building a small application simulating a horse race in order to gain some basic skill in working with threads.
My code contains this loop:
for (int i = 0; i < numberOfHorses; i++)
{
horsesThreads[i] = new Thread(horsesTypes[i].Race);
horsesThreads[i].Start(100);
}
In order to keep the race 'fair', I've been looking for a way to make all newly created threads wait until the rest of the new threads are set, and only then launch all of them to start running their methods (Please note that I understand that technically the threads can't be launched at the 'same time')
So basically, I am looking for something like this:
for (int i = 0; i < numberOfHorses; i++)
{
horsesThreads[i] = new Thread(horsesTypes[i].Race);
}
Monitor.LaunchThreads(horsesThreads);
Threading does not promise fairness or deterministic results, so it's not a good way to simulate a race.
Having said that, there are some sync objects that might do what you ask. I think the Barrier class (Fx 4+) is what you want.
The Barrier class is designed to support this.
Here's an example:
using System;
using System.Threading;
namespace Demo
{
class Program
{
private void run()
{
int numberOfHorses = 12;
// Use a barrier with a participant count that is one more than the
// the number of threads. The extra one is for the main thread,
// which is used to signal the start of the race.
using (Barrier barrier = new Barrier(numberOfHorses + 1))
{
var horsesThreads = new Thread[numberOfHorses];
for (int i = 0; i < numberOfHorses; i++)
{
int horseNumber = i;
horsesThreads[i] = new Thread(() => runRace(horseNumber, barrier));
horsesThreads[i].Start();
}
Console.WriteLine("Press <RETURN> to start the race!");
Console.ReadLine();
// Signals the start of the race. None of the threads that called
// SignalAndWait() will return from the call until *all* the
// participants have signalled the barrier.
barrier.SignalAndWait();
Console.WriteLine("Race started!");
Console.ReadLine();
}
}
private static void runRace(int horseNumber, Barrier barrier)
{
Console.WriteLine("Horse " + horseNumber + " is waiting to start.");
barrier.SignalAndWait();
Console.WriteLine("Horse " + horseNumber + " has started.");
}
private static void Main()
{
new Program().run();
}
}
}
[EDIT] I just noticed that Henk already mentioned Barrier, but I'll leave this answer here because it has some sample code.
I'd be looking at a ManualResetEvent as a gate; inside the Thread, decrement a counter; if it is still non-zero, wait on the gate; otherwise, open the gate. Basically:
using System;
using System.Threading;
class Program
{
static void Main()
{
ManualResetEvent gate = new ManualResetEvent(false);
int numberOfThreads = 10, pending = numberOfThreads;
Thread[] threads = new Thread[numberOfThreads];
ParameterizedThreadStart work = name =>
{
Console.WriteLine("{0} approaches the tape", name);
if (Interlocked.Decrement(ref pending) == 0)
{
Console.WriteLine("And they're off!");
gate.Set();
}
else gate.WaitOne();
Race();
Console.WriteLine("{0} crosses the line", name);
};
for (int i = 0; i < numberOfThreads; i++)
{
threads[i] = new Thread(work);
threads[i].Start(i);
}
for (int i = 0; i < numberOfThreads; i++)
{
threads[i].Join();
}
Console.WriteLine("all done");
}
static readonly Random rand = new Random();
static void Race()
{
int time;
lock (rand)
{
time = rand.Next(500,1000);
}
Thread.Sleep(time);
}
}
So according to MSDN, and many other places I've read, they use a semaphore and block within the individual threads, like so:
private static Semaphore _pool;
public static void Main()
{
_pool = new Semaphore(0, 3);
for(int i = 1; i <= 1000; i++)
{
Thread t = new Thread(new ParameterizedThreadStart(Worker));
t.Start(i);
}
}
private static void Worker(object num)
{
try
{
_pool.WaitOne();
// do a long process here
}
finally
{
_pool.Release();
}
}
Wouldn't it make more sense to block the process so that you don't create potentially 1000s of threads all at once depending on the number of iterations in Main()? For example:
private static Semaphore _pool;
public static void Main()
{
_pool = new Semaphore(0, 3);
for(int i = 1; i <= 1000; i++)
{
_pool.WaitOne(); // wait for semaphore release here
Thread t = new Thread(new ParameterizedThreadStart(Worker));
t.Start(i);
}
}
private static void Worker(object num)
{
try
{
// do a long process here
}
finally
{
_pool.Release();
}
}
Maybe both ways are not wrong and it depends on the situation? Or there is a better way to do this once there are a lot of iterations?
Edit: This is a windows service, so I'm not blocking the UI thread.
The reason you would normally do it inside the thread is you want to make that exclusive section as small as possible. You don't need the entire thread synchronized, only where that thread accesses the shared resource.
So a more realistic version of Worker is
private static void Worker(object num)
{
//Do a bunch of work that can happen in parallel
try
{
_pool.WaitOne();
// do a small amount of work that can only happen in 3 threads at once
}
finally
{
_pool.Release();
}
//Do a bunch more work that can happen in parallel
}
(P.S. If you are doing something that uses 1000 threads, you are doing something wrong. You should likely rather be using a ThreadPool or Tasks for many short-lived workloads or make each thread do more work.)
Here is how to do it with Parallel.ForEach
private static BlockingCollection<int> _pool;
public static void Main()
{
_pool = new BlockingCollection<int>();
Task.Run(() => //This is run in another thread so it shows data is being taken out and put in at the same time
{
for(int i = 1; i <= 1000; i++)
{
_pool.Add(i);
}
_pool.CompleteAdding(); //Lets the foreach know no new items will be showing up.
});
//This will work on the items in _pool, if there is no items in the collection it will block till CompleteAdding() is called.
Parallel.ForEach(_pool.GetConsumingEnumerable(), new ParallelOptions {MaxDegreeOfParallelism = 3}, Worker);
}
private static void Worker(int num)
{
// do a long process here
}
I have this simple program using threads in C#. How can I make sure that all the threads are done executing before I do a Console.ReadKey(); to terminate the program (else it goes straight to the ReadKey and I have to press it for the threads to keep executing)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace Partie_3
{
class Program
{
static int _intToManipulate;
static object _lock;
static Thread thread1;
static Thread thread2;
static void Main(string[] args)
{
_intToManipulate = 0;
_lock = new object();
thread1 = new Thread(increment);
thread2 = new Thread(decrement);
thread1.Start();
thread2.Start();
Console.WriteLine("Done");
Console.ReadKey(true);
}
static void increment()
{
lock (_lock)
{
_intToManipulate++;
Console.WriteLine("increment : " + _intToManipulate);
}
}
static void decrement()
{
lock (_lock)
{
_intToManipulate--;
Console.WriteLine("decrement : " + _intToManipulate);
}
}
}
}
You're looking for Thread.Join():
thread1.Start();
thread2.Start();
thread1.Join();
thread2.Join();
Console.WriteLine("Done");
Console.ReadKey(true);
A similar question can be found here: C#: Waiting for all threads to complete
With C# 4.0+ I personally prefer to use Tasks instead of Threads and wait for them to complete as mentioned in the second highest voted answer:
for (int i = 0; i < N; i++)
{
tasks[i] = Task.Factory.StartNew(() =>
{
DoThreadStuff(localData);
});
}
while (tasks.Any(t => !t.IsCompleted)) { } //spin wait
Console.WriteLine("All my threads/tasks have completed. Ready to continue");
If you've got little experience with Threads and Tasks, I'd recommend going down the Tasks route. Comparitively, they're really simple to use.