您可以定义一个 Shuffle() 扩展方法来执行 Fisher-Yates-Durstenfeld shuffle(它以线性时间执行,而不是 OrderBy 的 NlogN 时间):
public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> input)
{
var buffer = input.ToArray();
//Math.Random is OK for "everyday" randomness;
//you should use RNGCryptoServiceProvider if you need
//cryptographically-strong randomness
var rng = new Math.Random();
//as the loop proceeds, the element to output will be randomly chosen
//from the elements at index i or above, which will then be swapped with i;
//the yield return gives us each shuffled value as it is chosen, and
//allows the shuffling to happen "lazily".
for (int i = 0; i < buffer.Length; i++)
{
int j = rng.Next(i, buffer.Length);
yield return buffer[j];
//if we cared about the elements in the buffer this would be a swap,
//but we don't, so...
buffer[j] = buffer[i];
}
}
//simple extension method to provide List.ForEach()-like functionality
//on any collection or IEnumerable.
public static void ForEach(this IEnumerable<T> collection, Action<T> action)
{
foreach(var element in collection) action(element);
}
//Usage - pretty much the same as Raphael's,
//but now you don't have to convert to a List to use ForEach:
rows.Shuffle().Take(25).ForEach(m => task1.Run(m));
rows.Shuffle().Take(50).ForEach(m => task2.Run(m));
rows.ForEach(m => task3.Run(m));