C# Thread seems to start multiple times-Collection of common programming errors

The issue is caused by the interaction between foreach loops and lambda capture.

The variable s is overwritten in each iteration of the foreach loop. This means that the reference to s captured by the lambda in new Thread has changed by the time the new thread is executed.

The first thread will execute successfully, but the remainder of the threads are also pointing to the same value of s and will fail.

The solution is to create a temporary variable:

foreach (String s in Directory.EnumerateFiles(@"C:\Test", "*.txt", SearchOption.TopDirectoryOnly))
{
  var temp = s;
  new Thread(() => File.Move(temp, temp + "ok")).Start();                
}

As per @Eric Lippert’s suggestion, consider using PLINQ or the TPL to manage the threading for you:

// assume `using System.Linq`

Directory.EnumerateFiles(@"C:\Test", "*.txt", SearchOption.TopDirectoryOnly)
         .AsParallel()
         .Select(f => File.move(f, f + "ok"))
         .ToList();

This neatly avoids the issues with foreach and gives the runtime control over the threading behaviour.