Pregunta

I have a Windows Service that processes tasks created by users. This Service runs on a server with 4 cores. The tasks mostly involve heavy database work (generating a report for example). The server also has a few other services running so I don't want to spin up too many threads (let's say a maximum of 4).

If I use a BlockingCollection<MyCustomTask>, is it a better idea to create 4 Thread objects and use these to consume from the BlockingCollection<MyCustomTask> or should I use Parallel.Foreach to accomplish this?

I'm looking at the ParallelExtensionsExtras which contains a StaTaskScheduler which uses the former, like so (slightly modified the code for clarity):

var threads = Enumerable.Range(0, numberOfThreads).Select(i =>
                       {
                           var thread = new Thread(() =>
                           {
                               // Continually get the next task and try to execute it.
                               // This will continue until the scheduler is disposed and no more tasks remain.
                               foreach (var t in _tasks.GetConsumingEnumerable())
                               {
                                   TryExecuteTask(t);
                               }
                           });
                           thread.IsBackground = true;
                           thread.SetApartmentState(ApartmentState.STA);
                           return thread;
                       }).ToList();

            // Start all of the threads
            threads.ForEach(t => t.Start());

However, there's also a BlockingCollectionPartitioner in the same ParallelExtensionsExtras which would enable the use of Parallel.Foreach on a BlockingCollection<Task>, like so:

 var blockingCollection = new BlockingCollection<MyCustomTask>();
        Parallel.ForEach(blockingCollection.GetConsumingEnumerable(), task =>
        {
            task.DoSomething();
        });

It's my understanding that the latter leverages the ThreadPool. Would using Parallel.ForEach have any benefits in this case?

¿Fue útil?

Solución

This answer is relevant if Task class in your code has nothing to do with System.Threading.Tasks.Task.

As a simple rule, use Parallel.ForEach to run tasks that will end eventually. Like execute some work in parallel with some other work

Use Threads when they run routine for the whole life of application.

So, it looks like in your case you should use Threads approach.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top