我有一个帐号列表。Foreach 帐号我需要调用方法ProcessAccount
。将有大约 150,000 个帐户需要处理,每个帐户可能需要 0.5 到 2 秒来处理。
我想以某种方式设置线程,以便我可以一次处理 4 个帐户。
我可以为此使用一个简单的模式吗?
我想做的是启动 4 个线程来处理前 4 个帐户,然后随着每个单独的线程完成,启动另一个具有下一个帐户的线程,直到所有帐户都已处理。
我有一个帐号列表。Foreach 帐号我需要调用方法ProcessAccount
。将有大约 150,000 个帐户需要处理,每个帐户可能需要 0.5 到 2 秒来处理。
我想以某种方式设置线程,以便我可以一次处理 4 个帐户。
我可以为此使用一个简单的模式吗?
我想做的是启动 4 个线程来处理前 4 个帐户,然后随着每个单独的线程完成,启动另一个具有下一个帐户的线程,直到所有帐户都已处理。
这很容易使用 TPL(任务并行库)处理。它看起来像
ParallelOptions options = new ParallelOptions() { MaxDegreeOfParallelism = 4 };
Parallel.ForEach(accounts, options, a =>
{
ProcessAccount(a);
});
http://msdn.microsoft.com/en-us/library/dd782721.aspx
请注意,TPL 可能会决定运行少于 4 个并发线程,但不会根据指定的选项运行超过 4 个。它可能会这样做,例如,如果它确定提供的 lamda(调用 ProcessAccount)受 CPU 限制并且系统上的 CPU 内核少于 4 个。通常,特别是在 .NET 4.5 中,TPL 对要使用的线程数做出了非常好的决定。
正如@Servy 在评论中指出的那样,除非您有非常具体的理由将代码限制为 4 个线程,否则最好让 TPL 自行整理要使用多少个线程。这样,如果相同的代码在 2018 年运行在 128 核处理器上,那么在你转移到其他东西很久之后,它就可以免费使用所有 128 核)。
使用 PLinq:
var accounts = //some 150,000 account numbers
accounts.AsParallel().ForAll(ProcessAccount);
或者,如果需要其他参数,请使用 lambda 表达式:
accounts.AsParallel().ForAll(account => ProcessAccount(account, argument2, argument3));