0

I have a collection of objects. I need to process each of these objects in separate threads in order one by one. A number of simultaneous threads should be fixed, say 4. What is the best way to do this given that I'm limited by .NET Framework of version 3.5?

EDIT: By "in order" I meant that at the beginning processing of the first object should start. Then while it is still processed the processing of second, third and fourth object starts. Fifth object will wait for any of these four objects processing to be finished. Etc. But, say, sixth object cannot be processed if fifth didn't. You may have noticed some of download managers works this way.

user10101
  • 1,704
  • 2
  • 20
  • 49
  • Thread-safe queues are nice .. I wonder if there is a back-port of (parts of) the TPL? –  Aug 28 '12 at 22:33
  • 4
    If they need to be "in order" and "one by one" how can this be done more efficiently by more than one thread? – spender Aug 28 '12 at 22:35
  • 1
    Please clarify what you mean by "in order". Do you mean that your final result must contain the items being processed in the same order that they occurred originally, or that they need to be sorted by a specific criteria? – JamieSee Aug 28 '12 at 22:40
  • Please see my edit to the original post. – user10101 Aug 28 '12 at 22:48
  • Getting the index of the next object in your collection to be processed could be done with something as simple as Interlocked.Increment http://msdn.microsoft.com/en-us/library/dd78zt0c%28v=vs.90%29.aspx – hatchet - done with SOverflow Aug 28 '12 at 23:01
  • @pst - [See this post](http://stackoverflow.com/questions/2987439/can-i-use-the-task-parallel-library-in-a-net-3-5-project) that specifies how parts of PFX are available for 3.5, by use of the Reactive Extensions. – Chris O Aug 28 '12 at 23:33

2 Answers2

0

I'm assuming that it's okay in your description for item 6 to be dealt with once item 5's process has started, even if it isn't finished.

Sounds like a natural job for a ConcurrentQueue<T>, but that's 4.0.

LLQueue can be ported to 3.5 if you cut out the support for IProducerConsumerCollection<T>, since that's 4.0, but the rest should run on anything from 2.0 up.

Then just have 4 (or however many) threads that each keep calling TryDequeue until it returns false, and if it returns true then processing the item obtained.

Jon Hanna
  • 110,372
  • 10
  • 146
  • 251
0

You question is a little confusing to me. I don't know why you want to process in batches of 4?

This process parallel on batches of 4. The order in the batch in not guaranteed.

public void ParallelOne()
    {
        int[] nums = Enumerable.Range(0, 8).ToArray();
        Debug.WriteLine(nums.Count().ToString() + " " + nums[nums.Count()-1].ToString());
        long total = 0;


        for (int k = 0; k < 2; k++)
        {
            total = 0;
            // Use type parameter to make subtotal a long, not an int
            Parallel.For<long>(k*4, (k+1)*4, () => 0, (j, loop, subtotal) =>
            {
                subtotal += nums[j];
                Debug.WriteLine(subtotal.ToString() + " " + j.ToString());
                return subtotal;
            },
                (x) => Interlocked.Add(ref total, x)
            );

            Debug.WriteLine("The total is {0}", total);
        }

    }

If you want dynamic parallel with 4 thread then just use Paralled.ForEach and use WithDegreeOfParallelism to throttle the treads to 4.

paparazzo
  • 44,497
  • 23
  • 105
  • 176