You need to select a series of elements for each call to ProcessCopy() - right now you are passing each thread a complete listing of the files - remember that the IEnumerable you pass has a method called GetEnumerator() - only when this method is called (which foreach does for you under the hood) returns a real counter, with which you can list items one by one. Since you pass in IEnumerable , each thread calls GetEnumerator() and therefore lists all the files.
Instead, do something like this so that each ProcessCopy() processes a single file:
foreach(string file in GetFiles(source)) { string fileToProcess = file; tasks.Add(Task.Factory.StartNew(() => { ProcessCopy(fileToProcess); })); } Task.WaitAll(tasks.ToArray());
I would not worry about the number of processors - let the TPL and the thread pool determine the number of threads for optimal performance.
Brokenglass
source share