Yesterday, I made my first multithreaded tests with XNA 4.0.
I started with my own WorkerThreadManager
, a BlockingQueue
and some WaitHandles
to setup a Worker-Queue and Workers. The testproject was a an XNA-App just drawing circles and move them around (with collision detection on the walls). The first test was rather disappointing. I could run about 4x more circles in single-threaded mode than with multi-threaded approach.
After some profiling, I found that the BlockingQueue
was the bottleneck. I then found the class BlockingCollection from .Net 4.0. Using that one improved the speed quite a bit but still about 3x slower than the single-threaded one.
After some more research, I stumbled accross the brand-new System.Threading.Tasks Namespace with some quite interesting classes.
I could replace my whole ThreadManager with this little piece of code:
List<Agent> agentList = SomeHowGetSomeAgents();
Task[] tasks = new Task[agentList.Count];
for (int index = 0; index < agentList.Count; index++)
{
Agent agent = agentList[index];
Task t = Task.Factory.StartNew(() => DoSomeWork(agent));
tasks[index] = t;
}
Task.WaitAll(tasks);
Nice, eh. That further improved the speed but again, it’s still about 2x slower than the single-threaded one…
So I found one more class called Parallel.
With this class, the code now looks like:
List<Agent> agentList = SomeHowGetSomeAgents();
Parallel.ForEach(agentList, DoSomeWork);
That one finally runs faster than the single-threaded approach. Three times faster!
I might need to redo all those tests when the DoSomeWork
is much more sophisticated. But for now, Parallel
seems the way to go for simple Worker-Threads.
More on this Topic: