Are there any changes that several background workers perform better than tasks on 5 second running processes? I remember reading in a book that the task is for short running processes.
I ask the following:
I have a process that takes 5 seconds and 4,000 processes terminate. First I did:
for (int i=0; i<4000; i++) { Task.Factory.StartNewTask(action); }
and it had poor performance (after the first minute, 3-4 tasks where it was completed, and the console application had 35 threads). It might have been stupid, but I thought that the thread pool would handle this situation (it would put all the actions in the queue, and when the thread is free, it would take an action and execute it).
The second step now was to manually do the Background Environment.ProcessorCount workspaces and all the actions that need to be placed in ConcurentQueue. Thus, the code will look something like this:
var workers = new List<BackgroundWorker>(); //initialize workers workers.ForEach((bk) => { bk.DoWork += (s, e) => { while (toDoActions.Count > 0) { Action a; if (toDoActions.TryDequeue(out a)) { a(); } } } bk.RunWorkerAsync(); });
It has improved. He performed much better tasks, even when I had 30 background workers (as many tasks as in the first case).
LE:
I run the following tasks:
public static Task IndexFile(string file) { Action<object> indexAction = new Action<object>((f) => { Index((string)f); }); return Task.Factory.StartNew(indexAction, file); }
And the Index method is this:
private static void Index(string file) { AudioDetectionServiceReference.AudioDetectionServiceClient client = new AudioDetectionServiceReference.AudioDetectionServiceClient(); client.IndexCompleted += (s, e) => { if (e.Error != null) { if (FileError != null) { FileError(client, new FileIndexErrorEventArgs((string)e.UserState, e.Error)); } } else { if (FileIndexed != null) { FileIndexed(client, new FileIndexedEventArgs((string)e.UserState)); } } }; using (IAudio proxy = new BassProxy()) { List<int> max = new List<int>(); if (proxy.ReadFFTData(file, out max)) { while (max.Count > 0 && max.First() == 0) { max.RemoveAt(0); } while (max.Count > 0 && max.Last() == 0) { max.RemoveAt(max.Count - 1); } client.IndexAsync(max.ToArray(), file, file); } else { throw new CouldNotIndexException(file, "The audio proxy did not return any data for this file."); } } }
These methods read some data from an mp3 file using the Bass.net library. This data is then sent to the WCF service using the async method. The IndexFile method (a string file) that creates tasks is called 4,000 times in a for loop. These two events, FileIndexed and FileError, are not processed, so they are never thrown.