Spawning Workflows

In C #,

How could I multiply multiple threads and then sequentially add the results to the list before returning the entire result set?

What are some best practices?

I still use ManualResetEvent to signal when the last item has been processed by a thread.

But when he returns, I need them to consolidate the result sets in a sequential order so that we don’t get into conflicting problems with the list of return values ​​(final results).

+4
source share
4 answers

If you know the final order before you create the streams (which is implied "sequentially"), you can transfer the index to each stream and write its results to this "slot" in the array. Thus, when all threads have completed processing (in any order), the results will already be ordered correctly, avoiding the need for sorting after processing.

+1
source

The parallel task library, which is now part of the Reactive Extensions for.NET Framework , makes such things trivial. There are a set of Parallel constructors for parallelizing code and a set of thread-safe Concurrent{Container}s that you can use with them.

Here's an example of plotting the number of rows using Parallel.For and a ConcurrentBag to store the results.

 using System.Threading.Tasks; using System.Collections.Concurrent; namespace ParallelTest { class Program { static void Main(string[] args) { var results = new ConcurrentBag<int>(); Parallel.For(0, 10, i => { results.Add(i * i); }); foreach (int i in results) System.Console.WriteLine(i); } } } 

ConcurrentBag is a regular IEnumerable , as you can see that I am using a regular, non-parallel foreach to print the results at the end.

Note. All this is actually standard in .NET 4.0, you just need Rx if you want it for .NET 3.5.

+1
source

If you use .Net 4, you can, for example, use the Task class. Here is an example of merging List

 Task<List<string>> task1 = new Task<List<string>>(SomeFunction); Task<List<string>> task2 = new Task<List<string>>(SomeFunction); task1.Start(); task2.Start(); var taskList = new List<Task<List<string>>> {task1, task2}; Task.WaitAll(taskList.ToArray()); List<string> res = new List<string>(); foreach (Task<List<string>> t in taskList) { res.AddRange(t.Result); } 

and your function

 List<string> SomeFunction() { return new List<string>{"1","2"}; } 
+1
source

When you start each thread, pass it your sequence identifier and callback method and increase the counter, which indicates the total number of threads started. When each thread ends, it calls the callback method, which decreases the counter of the executed threads and inserts the results into the SortedDictionary with the sequence identifier key. When the last thread is completed, a callback may signal your main routine.

0
source

Source: https://habr.com/ru/post/1307710/


All Articles