0

I find that I am enjoying the simplicity of running code asynchronously through BackgroundWorkers. I have taught myself through example or trial and error on its uses, pitfalls, safe-threading etc., not so much the theory and perhaps my Achilles heel.

I have done my reserach but one thing I don't find very much talk of, how can I effectively create and use a pool of BackgroundWorkers? Or what is a better alternative that is just as simple as using BWs?

I will illustrate the problem I am running into: I had a task X, Y, and Z, each one intensive, thus it will hang up the UI thread. I decided BWs are the answer, EVEN, if this code was executed only once. I learned how to use them, some safe threading practices, and went on my way. Pretty soon my code looked like: BW1, BW2, BW3, and so forth.

Then I began to get more familiar with them and really put in code into BWs that can be used for Hardware Monitoring or other infinite looped / always running items. I still ran into a BW5, BW6.... issue.

I found creative ways to have multipurpose BackgroundWorkers by having a Global String Variable which was set before RunWorkerAsynchronous() was called and then I could either have Nested If/Elses or Switches inside the BackgroundWorker to execute the code that was needed based off of what I set the String Variable to. However, I feel I am just dancing around a limit of my self-learning.

So can anyone guide me through the concept of creating a Pool of Threads/BWs and use them as needed throughout my program, recycling the threads instead of explicitly creating each one, then having dozens of backgroundworkers for specific intensive purposes to juggle?

Note: I am not a very good programmer so I am looking for simple functional examples or explanations. Any and all help though is eagerly welcome!

HouseCat
  • 1,559
  • 20
  • 22
  • Have you looked at Tasks (TPL) and/or the regular ThreadPool? IIRC, backgroundworker is good if you need a synchronization context for updating a WPF or Winforms UI, but it's not exactly flexible. – x0n Oct 16 '14 at 15:46
  • have you checked the [ThreadPool Class](http://msdn.microsoft.com/en-us/library/System.Threading.ThreadPool(v=vs.110).aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-1) – bansi Oct 16 '14 at 15:46
  • Is this .NET 2.0 or higher? – Fabian Bigler Oct 16 '14 at 15:48
  • Thanks guys, I will have a look at Tasks and ThreadPool. @fabigler .Net 4.5.1 / .2 – HouseCat Oct 16 '14 at 15:50

2 Answers2

2

I highly recommend using Tasks to achieve what you want. This manages all the hard work of selecting threads from the thread pool, balancing the threads across multiple cores etc.

if you have the function:

public void DoSomething()
{
    //things happen here
}

Then you can start tasks using:

var task = Task.Factory.StartNew(DoSomething);

or

var task = new Task(DoSomething);

You can read more at http://msdn.microsoft.com/en-us/library/dd537609(v=vs.110).aspx

Anduril
  • 1,236
  • 1
  • 9
  • 33
  • 1
    +1 for looking into Tasks. They are very flexible: they're usable with `async/await`; they support chaining/continuations and child tasks; they have an efficient scheduler; they support cancellation; they play nice with `SynchronizationContext`; and if you have a long-running task, you can pass `TaskCreationOptions.LongRunning` to ensure it gets its own thread and doesn't block new tasks from being scheduled. If you're moving from a high-level construct like `BackgroundWorker`, this will be a much more natural transition than simply firing jobs at the `ThreadPool`. – Mike Strobel Oct 16 '14 at 16:08
  • Thanks for the additional information, I was hoping I had a few more months of using my code, but it looks like I have to "grow up" and use big boy programming now. – HouseCat Oct 16 '14 at 16:17
1

You don't need to pool them. They use internally the ThreadPool, that is already a pool of threads.

Thread/threadpool or backgroundworker

Community
  • 1
  • 1
vtortola
  • 34,709
  • 29
  • 161
  • 263
  • I understand this, however, the BackgroundWorker is explicit the code. It is never waivering sometimes disposable, other times it isn't. How do I avoid declaring a dozen BWs, when some of the time they need to be re-used while others are "disposable"? My thoughts tell me to create a HastTable/Array/List of BWs... but I thought there might be a better way. – HouseCat Oct 16 '14 at 15:49
  • Well, if you are creating dozens of BWs ... you may want to rethink your approach :) Use something like TPL and you will discover a new world of control http://www.codeproject.com/Articles/747594/Understanding-Task-Parallelism-Framework-TPL-using BW are just for saving the day, never thought to be used that way. – vtortola Oct 16 '14 at 15:56
  • Will do TPL seems like the answer, there is just so much reworking to be done... ugh. I actually got recommend to BWs to begin with from a Microsoft Dev. Thanks for the help :) – HouseCat Oct 16 '14 at 15:59
  • BW are great when you are in Windows Forms and you want to spaw a piece of work in another thread. But when things get more complicated, you have many parallel operations and you start to need things like pooling, throttling, etc... it is time to move to the next level. – vtortola Oct 16 '14 at 16:02
  • With TPL you can use things like DataFlow to have a very good control on your parallel work: http://msdn.microsoft.com/en-us/library/hh228603(v=vs.110).aspx – vtortola Oct 16 '14 at 16:03
  • 1
    It appears I have to step up to the big boy plate. It will take me a while to learn PLINQ though, not very familiar with Lambda / LINQ. Anywho, have a Guinness on me tonight ;) – HouseCat Oct 16 '14 at 16:14