6

I would like to know what to use for tasks that need alot of performance. Backgroundworker, Thread or ThreadPool?

I've been working with Threads so far, but I need to improve speed of my applications.

jabaldonedo
  • 25,822
  • 8
  • 77
  • 77
user2468035
  • 88
  • 1
  • 4

3 Answers3

14

BackgroundWorker is the same thing as a thread pool thread. It adds the ability to run events on the UI thread. Very useful to show progress and to update the UI with the result. So its typical usage is to prevent the UI from freezing when works needs to be done. Performance is not the first goal, running code asynchronously is. This pattern is also ably extended in later .NET versions by the Task<> class and the async/await keywords.

Thread pool threads are useful to avoid consuming resources. A thread is an expensive operating system object and you can create a very limited number of them. A thread takes 5 operating system handles and a megabyte of virtual memory address space. No Dispose() method to release these handles early. The thread pool exists primarily to reuse threads and to ensure not too many of them are active. It is important that you use a thread pool thread only when the work it does is limited, ideally not taking more than half a second. And not blocking often. It is therefore best suited for short bursts of work, not anything where performance matters. Handling I/O completion is an ideal task for a TP thread.

Yes, it is possible to also use threads to improve the performance of a program. You'd do so by using Thread or a Task<> that uses TaskContinuationOptions.LongRunning. There are some hard requirements to actually get a performance improvement, they are pretty stiff:

  • You need more than one thread. In an ideal case, two threads can half the time needed to get a job done. And less, the more threads you use. Approaching that ideal is however hard, it doesn't infinitely scale. Google "Amdahl's law" for info.
  • You need a machine with a processor that has multiple cores. Easy to get these days. The number of threads you create should not exceed the number of available cores. Using more will usually lower performance.
  • You need the kind of job that's compute-bound, having the execution engine of the processor be the constrained resource. That's fairly common but certainly no slamdunk. Many jobs are actually limited by I/O throughput, like reading from a file or dbase query. Or are limited by the rate at which the processor can read data from RAM. Such jobs don't benefit from threads, you'll have multiple execution engines available but you still have only one disk and one memory bus.
  • You need an algorithm that can distribute the work across multiple threads without hardly any need for synchronization. That's usually the tricky problem to solve, many algorithms are very sequential in nature and are not easily parallelizable.
  • You'll need time and patience to get the code stable and performing well. Writing threaded code is hard and a threading race that crashes your program once a month, or produces an invalid result occasionally can be a major time sink.
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • great answer! i think i got what I need. how do i close this question? (I am new to this). – user2468035 Jun 09 '13 at 17:39
  • @user - Just mark it answered. Click the check-mark to the left of the post that answered your question. – Hans Passant Jun 09 '13 at 17:39
  • You say not to use a BackgroundWorker for long running tasks (and instead use `Thread` or `Task`). Is this because it's slower compared to Thread/Task, or is it memory-related, or it because it bogs the system down, or is it some other issue? Let's assume an embarrassingly-parallel problem with about 4-20 cores/threads (with the physical cores to match), and where the problem could take minutes to solve. – Dan W May 09 '16 at 07:53
  • You already know this from your last question, no point in asking it again. – Hans Passant May 09 '16 at 08:11
  • How could you even state that "In an ideal case, you can half the time needed to get a job done when you use two threads." – omerfarukdogan May 19 '16 at 14:18
  • No idea how I couldn't, even phones have multi-core processors today. – Hans Passant May 19 '16 at 14:25
1

The framework for initiating CPU-intensive tasks in threads is irrelevant to your problem, unless you have overly-small-grained subtasks.

You need to split your work into subtasks that can be executed in parallel when you have more than one CPU to do so.

Will
  • 73,905
  • 40
  • 169
  • 246
  • thanks, this actually increased speed. its doing multiple tasks at the same time now wich improved my performance. thanks again – user2468035 Jun 09 '13 at 11:17
0

This choice doesn't really matter. BackgroundWorker is a ThreadPool thread so that's no difference anyway. However, you could try to optimze the number of threads with ThreadPool.SetMaxThreads.

And you may want to use the System.Threading.Task class which could help to optimize parallel execution.

JeffRSon
  • 10,404
  • 4
  • 26
  • 51