c# - Parallel.ForEach 循环只允许一个线程访问 C# 中的数据库
问题描述
我有一段代码,其中多个线程使用来自 ConcurrentBag 类型字符串的共享 ID 属性进行访问,如下所示:
var ids = new ConcurrentBag<string>();
// List contains lets say 10 ID's
var apiKey = ctx.ApiKey.FirstOrDefault();
Parallel.ForEach(ids, id =>
{
try
{
// Perform API calls
}
catch (Exception ex)
{
if (ex.Message == "Expired")
{
// the idea is that if that only one thread can access the DB record to update it, not multiple ones
using (var ctx = new MyEntities())
{
var findApi= ctx.ApiKeys.Find(apiKey.RecordId);
findApi.Expired = DateTime.Now.AddHours(1);
findApi.FailedCalls += 1;
}
}
}
});
因此,在这种情况下,如果我有一个包含 10 个 ID 和 1 个密钥的列表用于 API 调用,一旦密钥达到每小时调用限制,我将从 API 捕获异常,然后将密钥标记为用于接下来的一个小时。
但是,在我上面粘贴的代码中,所有 10 个线程都将从 DB 访问记录并将失败的调用计为 10 次,而不是只有 1..:/
所以我的问题是如何防止所有线程更新数据库记录,而是只允许一个线程访问数据库,更新记录(通过+1添加失败的调用)?
我怎样才能做到这一点?
解决方案
如果发生错误,您似乎只需要更新一次 apiKey.RecordId ,为什么不跟踪发生错误的事实并在最后更新一次呢?例如
var ids = new ConcurrentBag<string>();
// List contains lets say 10 ID's
var apiKey = ctx.ApiKey.FirstOrDefault();
var expired = false;
Parallel.ForEach(ids, id =>
{
try
{
// Perform API calls
}
catch (Exception ex)
{
if (ex.Message == "Expired")
{
expired = true;
}
}
}
if (expired)
{
// the idea is that if that only one thread can access the DB record to
// update it, not multiple ones
using (var ctx = new MyEntities())
{
var findApi= ctx.ApiKeys.Find(apiKey.RecordId);
findApi.Expired = DateTime.Now.AddHours(1);
findApi.FailedCalls += 1;
}
});
推荐阅读
- ruby-on-rails - 如何在页面加载时在 AMP 页面中执行自定义 javascript 或外部 js?
- python - python - 如何将未引用的json字符串解析为python中的dict?
- java - Java (Android):根据 JWA (RFC 7518) 的 Diffie-Hellman 密钥交换过程
- php - 使用另一个值数组对数组进行排序
- c++ - 我怎样才能为每个编译的程序/动态库完成一个对象的单个实例?
- aframe - 如何在 A-frame 中创建滚动文本
- css - 使图像在具有固定高度的网格中响应
- powershell - PowerShell - 读取 SharePoint 文件属性(修改日期等)
- mongodb - 如何使用mongo查询在mongodb中存储的json数据的特定属性中查找特殊字符
- c - C中的多线程矩阵乘法