【发布时间】:2020-09-05 17:15:39
【问题描述】:
我有一个控制台应用程序,它执行下面提到的 3 个步骤,
- 从 db 获取待处理的通知记录
- 调用服务发送电子邮件(服务返回电子邮件地址作为响应)
- 得到服务响应后,更新数据库
对于第 2 步,我使用的是 Parallel.Foreach(),它的效果比 foreach() 好得多。 我已经阅读了很多关于 stackoverflow 的文章和线程,这在这个主题上造成了更多的混乱。 我有几个问题
- 我在服务器上运行它,它会影响性能吗?我应该限制线程数吗? (电子邮件数量可以是 0-500 或 1000)
- 我遇到了一个问题,在第 2 步中,服务返回了一个电子邮件地址作为响应,但在更新数据库时它不可用。 (这里的电子邮件数量是 400) 我怀疑这个问题可能是因为使用了 parallel.foreach 并且它没有添加到 notifList 中。 如果是这种情况,我可以在 Parallel.Foreach() 循环结束后添加 Thread.Sleep(1000),是否可以解决问题?
- 万一出现异常,我应该明确取消线程吗?
感谢您花时间和精力帮助我。谢谢!
public void notificationMethod()
{
List<notify> notifList = new List<notify>();
//step 1
List<orders> orderList = GetNotifs();
try
{
if (orderList.Count > 0)
{
Parallel.ForEach(orderList, (orderItem) =>
{
//step 2
SendNotifs(orderItem);
notifList.Add(new notify()
{
//building list by adding email address along with other information
});
});
if (notifList.Count > 0)
{
int index = 0;
int rows = 10;
int skipRows = index * rows;
int updatedRows = 0;
while (skipRows < notifList.Count)
{
//pagination
List<notify> subitem = notifList.Skip(index * rows).Take(rows).ToList<notify>();
updatedRows += subitem.Count;
//step 3
UpdateDatabase(subitem);
index++;
skipRows = index * rows;
}
}
}
}
catch (ApplicationException ex)
{
}
}
【问题讨论】:
-
我认为您应该使用一种专门的并发集合类型(用于 notifList),而不是 List
,我会使用 ConcurrentBag 看看是否能解决问题跨度> -
除了@StewartRitchie 评论,我建议您也为此使用任务并行库。该库为您完成大部分线程管理,并且有一些方法可以捕获和处理每个请求的异常。没有直接涉及线程,因此通常使用起来也更安全。然后,您可以使用
await foreach()并行运行这些。 Review the docs here 了解更多详情。 -
@NikP 如果他们正在使用
Parallel.ForEach,他们已经在使用 TPL。您引用的内容是否更具体? -
扩展@StewartRitchie 提到的内容:
List<T>不是线程安全的。如果多个线程同时添加项目,您肯定会丢失一些。ConcurrentBag<T>是线程安全的。
标签: c# .net console-application parallel.foreach .net-4.6.1