c# - 使用 Parallel.Foreach 更新具有线程安全性的实体属性
问题描述
我正在尝试利用 Parallel.Foreach 来更新实体的属性:联系人,如代码示例中所示
var contactIds = new List<int>();
contactIds.AddRange(res.RelatedContacts.Select(c => c.IdVal).ToList());
contacts = await _dbContext.Contacts.Where(co => contactIds.Contains(co.ContactId)).ProjectTo<ContactDTO>(_mapper.ConfigurationProvider).AsNoTracking().ToListAsync();
foreach (var contactrec in contacts)
{
var contact = contacts.FirstOrDefault(c => c.ContactId.Equals(contactrec.ContactId));
if (contact != null)
{
contact.address = addresses.FirstOrDefault(a => a.AddressId.Equals(contact.AddressId));
contact.ImagePath = contact.ImageId > 0 ? images.FirstOrDefault(im => im.ImageId.Equals(contact.ImageId)).FilePath : "NA";
}
}
我想用具有线程安全性的 Parallel.Foreach 替换上面的代码。
解决方案
我同意这些评论,那里有一些代码味道,并且可能以更有效的方式编写查询会比任何通过并行获得的优化更快地加速整个过程。
话虽如此,我认为您正在寻找这样的东西:
var contactIds = new List<int>();
contactIds.AddRange(res.RelatedContacts.Select(c => c.IdVal).ToList());
contacts = await _dbContext.Contacts.Where(co => contactIds.Contains(co.ContactId)).ProjectTo<ContactDTO>(_mapper.ConfigurationProvider).AsNoTracking().ToListAsync();
Parallel.Foreach(contacts, contact => Update(contact));
//or: Parallel.Foreach(contacts, Update);
void Update(Contact contact){
contact.address = addresses.FirstOrDefault(a => a.AddressId.Equals(contact.AddressId));
contact.ImagePath = contact.ImageId > 0 ? images.FirstOrDefault(im => im.ImageId.Equals(contact.ImageId)).FilePath : "NA";
}
一些注意事项:
- 无需遍历 Id,然后获取具有该 Id 的第一个元素。只需迭代元素。
- 不应该有任何线程安全问题,其中的操作
Update
是只读的。
推荐阅读
- python - 与熊猫中的布尔值进行比较时,我是否必须偏离 PEP 8 样式约定?
- java - 如何在 java、spring boot 中显示/测量 tibco 队列/主题的深度和阈值
- c# - 环绕面板上的 WPF 滚动条变灰
- java - JSON file processing with a different structure
- plc - rsLogix 5000, program structure to handle 30 motors simultaneously
- r - Applying data frame name in list to specific column in R
- javascript - Node.js console.log() 给出了不可预测的答案
- azure - 等待活动中的等待时间可以变化吗?
- php - 我的会话没有建立
- ios - 在 UITableView Swift 中添加 UIView 高于所有部分