Array of threads, only a few active at a time?

Apologies if this is simple question, but Im extremely worn down and though thinking straight. I recently set up threading and its working great. The user selects items to have work performed on, and I dynamicaly create an array of Threads for however many items they select and dispatch one thread per item.

However, I noticed that if too many are selected the server the files are on doesnt play nice. I know for a fact that I can declare only 5 active threads a time, even if there are 30 items that need work, but I can't wrap my head around it.

PS: If Im describing ThreadPool let me know... Ive tried to get that to work but had a hell of a time and no luck, pretty new to .NET way of threading.

Current way:

threadedResults = new List<string>[SelectedItems.Count];
List<string> results = new List<string>();
ThreadSettings tsArgs = (ThreadSettings)args;

for (int i = 0; i < SelectedItems.Count; i++)
{
    threadedResults[i] = new List<string>();
}

Thread[] threads = new Thread[SelectedItems.Count];

for (int i = 0; i < SelectedItems.Count; i++)
{
    KeyValuePair<int, ThreadSettings> threadArgs = new KeyValuePair<int, ThreadSettings>(i, (ThreadSettings)tsArgs);

    threads[i] = new Thread(new ParameterizedThreadStart(DoWork));
    threads[i].Start(threadArgs);
}
for (int i = 0; i < SelectedItems.Count; i++)
{
    if (CommandTask != null)
        threads[i].Join();
    else
    {
        // User Cancelled, abort all threads and break
        for (int j = 0; j < SelectedItems.Count; j++)
        {
            threads[j].Abort();
        }
        break;
    }
}

// Gather all results, format and return

Answers


Basically, you'd want to do something like this in the TPL:

        // source for cancelling work
        var cxlSource = new CancellationTokenSource();

        // create and schedule tasks to start
        var tasks =
            Enumerable.Range(0, SelectedItems.Count)
                .Select(i => Task.Factory.StartNew(DoWork, yourStateInfo, cxlSource.Token))
                .ToArray();

        // then wait for the results
        Task.WaitAll(tasks);

If at any time, you need to cancel the tasks, you can request a cancel:

            cxlSource.Cancel();

Which will prevent any tasks awaiting execution from starting, and your tasks can examine the token themselves periodically so they can abort early if cancelled while in progress.

There's a lot of nuance to using the TPL (and threading in general), but that's a rough idea.


If you want to stick to you version, I would declare Environment.ProcessorCount number of threads, instead of 5 (if you have 2 processors, only 2 of the 5 threads will be running on the same time). Too many threads causes overhead in the system (and that may be the problem for you).

If not, consider using Task in .net 4, or the TreadPool.


Need Your Help

Case insensitivity for DB Collation - does it affect performance?

database collation

Earlier on while I was working on my databases, I wondered if using a case sensitive collation like utf8_bin would increase performance over case insensitive collaction like utf8_general_ci (exampl...