下面是這樣做的手動方法。
您需要一個隊列。隊列是未完成任務的序列。您必須將其出列並放入工作任務列表中。當任務完成後,將其從工作任務列表中刪除,並從隊列中取出另一個任務。主線程控制這個過程。這裏是如何做到這一點的示例。
對於我使用的整數列表,但它應該適用於其他類型,因爲它使用泛型。
private static void Main()
{
Random r = new Random();
var items = Enumerable.Range(0, 100).Select(x => r.Next(100, 200)).ToList();
ParallelQueue(items, DoWork);
}
private static void ParallelQueue<T>(List<T> items, Action<T> action)
{
Queue pending = new Queue(items);
List<Task> working = new List<Task>();
while (pending.Count + working.Count != 0)
{
if (pending.Count != 0 && working.Count < 16) // Maximum tasks
{
var item = pending.Dequeue(); // get item from queue
working.Add(Task.Run(() => action((T)item))); // run task
}
else
{
Task.WaitAny(working.ToArray());
working.RemoveAll(x => x.IsCompleted); // remove finished tasks
}
}
}
private static void DoWork(int i) // do your work here.
{
// this is just an example
Task.Delay(i).Wait();
Console.WriteLine(i);
}
如果您遇到如何爲自己實施DoWork的問題,請讓我知道。因爲如果你改變方法簽名,你可能需要做一些改變。
更新
您還可以使用異步做到這一點等待,而不會阻塞主線程。
private static void Main()
{
Random r = new Random();
var items = Enumerable.Range(0, 100).Select(x => r.Next(100, 200)).ToList();
Task t = ParallelQueue(items, DoWork);
// able to do other things.
t.Wait();
}
private static async Task ParallelQueue<T>(List<T> items, Func<T, Task> func)
{
Queue pending = new Queue(items);
List<Task> working = new List<Task>();
while (pending.Count + working.Count != 0)
{
if (working.Count < 16 && pending.Count != 0)
{
var item = pending.Dequeue();
working.Add(Task.Run(async() => await func((T)item)));
}
else
{
await Task.WhenAny(working);
working.RemoveAll(x => x.IsCompleted);
}
}
}
private static async Task DoWork(int i)
{
await Task.Delay(i);
}
我喜歡的圖像 – Abdullah
如果@ USR的回答是不行的,看看[我的回答這裏](http://stackoverflow.com/a/15056827/106159)可能適用。否則,如果你可以使用TPL的DataflowBlock類,可能會更好(我想你不能,因爲你指定C#4) –
@Abdullah它只是缺少一些手繪紅圈 – TheLethalCoder