我強烈推薦使用自.NET 4.0起包含在.NET中的任務並行庫(TPL)。任務不是正好是線程,它們有效地抽象了線程池。
這對解釋與TPL有關的細微差異做了很好的工作:Multithreading or task parallel library。
[TestMethod]
public void ProcessBots()
{
string[] bots = new string[] { "A", "B", "C", "D", "E", "F", "G" };
Parallel.ForEach(bots, bot => //use if you just want to foreach
{
this.TestContext.WriteLine(bot);
});
Parallel.For(0, bots.Length, i => //use if you care about the index
{
this.TestContext.WriteLine(i.ToString());
});
}
Test Name: ProcessBots
Test Outcome: Passed
Result StandardOutput:
TestContext Messages:
A
D
E
F
G
B
C
0
2
3
4
5
1
6
,如果你需要溝通進展IProgress另一個有用的結構,它代表了推結果反饋給你的用戶界面上的需求標準合同。
[TestMethod]
public void ProcessBots()
{
string[] bots = new string[] { "A", "B", "C", "D", "E", "F", "G" };
IProgress<string> progress = new Progress<string>(str =>
{
this.TestContext.WriteLine(str);
});
Parallel.ForEach(bots, bot =>
{
progress.Report(bot);
});
Parallel.For(0, bots.Length, i =>
{
progress.Report(i.ToString());
});
}
如果您需要更多流式傳輸,您可能需要查看TPL數據流。 (nuget包Microsoft.TPL.DataFlow)。
[TestMethod]
public async Task ProcessBots()
{
string[] bots = new string[] { "A", "B", "C", "D", "E", "F", "G" };
BroadcastBlock<string> getBotsBlock = new BroadcastBlock<string>(bot => bot, new ExecutionDataflowBlockOptions() { MaxDegreeOfParallelism = ExecutionDataflowBlockOptions.Unbounded });
Random rand = new Random();
ActionBlock<string> processBotsBlock = new ActionBlock<string>(async bot =>
{
await Task.Delay(rand.Next(100, 1000));
TestContext.WriteLine(bot);
}, new ExecutionDataflowBlockOptions() { MaxDegreeOfParallelism = ExecutionDataflowBlockOptions.Unbounded });
ActionBlock<string> processBotsToLowerBlock = new ActionBlock<string>(async bot =>
{
await Task.Delay(rand.Next(100, 1000));
TestContext.WriteLine(bot.ToLower());
}, new ExecutionDataflowBlockOptions() { MaxDegreeOfParallelism = ExecutionDataflowBlockOptions.Unbounded });
getBotsBlock.LinkTo(processBotsBlock, new DataflowLinkOptions(){PropagateCompletion = true});
getBotsBlock.LinkTo(processBotsToLowerBlock, new DataflowLinkOptions() { PropagateCompletion = true });
foreach (var bot in bots) //note there is no parallelization here, you can post these on demand from any thread completely safe, where as the other solutions if the IEnumerable changes from another thread you have the potential for exceptions
getBotsBlock.Post(bot);
getBotsBlock.Complete();
await processBotsBlock.Completion;
await processBotsToLowerBlock.Completion;
}
Test Name: ProcessBots
Test Outcome: Passed
Result StandardOutput:
TestContext Messages:
c
A
G
B
f
b
e
F
C
a
d
g
E
D
謝謝,這是一個簡單的解決方案,完成了這項工作。 –