为什么我应该在全局级别定义 mongoDB 集合 - 它是线程安全的
Why should I define mongoDB collection at global level - It's thread safe
我正在使用 C++/Cli 来处理 mongoDB 编译为 dll 的最新 C# 驱动程序。我在 C++ 代码中使用驱动程序的一个实例。
我试过很多次了。如果我构建多个线程,每个线程都尝试更新同一个集合中的文档,似乎只有一个线程会成功。当我为线程设置睡眠时间时,它似乎工作正常。但是我需要在短时间内同时更新几千个文档,设置休眠时间不是一个有效的方法。
下面是线程的启动方式:
void updateKOOnMongo(int i, int k) {
time_t tn = time(NULL);
Sleep(max(1, (lastkoupdatetime - tn + 2) * 1000));
lastkoupdatetime = time(NULL);
MongoUpdates ^mgudt = gcnew MongoUpdates(i, k);
Thread ^updateko = gcnew Thread(gcnew ThreadStart(mgudt, &MongoUpdates::UpdateKO));
updateko->Start();
}
这是 MongoUpdates 中的函数:
void MongoUpdates::UpdateKO {
mongoImp->updateKO(i, k);
}
mongoImp is an instance of the mongoDB C# driver compiled as dll.
下面是 C# 驱动程序中的代码:
public static async void updateKO(int i, int k)
{
await updateKOdr(i, k);
}
static async Task updateKOdr(int i, int k)
{
string col = "ko." + i.ToString();
var collection = _database.GetCollection<BsonDocument>(col);
var builder = Builders<BsonDocument>.Filter;
var filter = builder.Eq("a", i) & builder.Lte("lf", k);
var update = Builders<BsonDocument>.Update.Set("status", 0);
var result = await collection.UpdateOneAsync(filter, update);
}
如果我删除以下部分:
time_t tn = time(NULL);
Sleep(max(1, (lastkoupdatetime - tn + 2) * 1000));
lastkoupdatetime = time(NULL);
如果两个或多个线程同时处理同一个集合,它几乎总是会失败。请帮忙。
我发现问题是我在每次更新操作中都创建了一个新的集合实例。这很糟糕,我没有注意到,因为代码是很久以前我对 mongoDB 还很陌生时编写的。 mongoDB 集合是线程安全的,所以我应该像这样在全局级别定义它:
protected static IMongoCollection<BsonDocument> _collection;
所以我可以使用它而无需每次都创建它的新实例。我只需要这样做:
if (_collection == null) {
_collection = _database.GetCollection<BsonDocument>("ko." + i.ToString());
}
我正在使用 C++/Cli 来处理 mongoDB 编译为 dll 的最新 C# 驱动程序。我在 C++ 代码中使用驱动程序的一个实例。
我试过很多次了。如果我构建多个线程,每个线程都尝试更新同一个集合中的文档,似乎只有一个线程会成功。当我为线程设置睡眠时间时,它似乎工作正常。但是我需要在短时间内同时更新几千个文档,设置休眠时间不是一个有效的方法。
下面是线程的启动方式:
void updateKOOnMongo(int i, int k) {
time_t tn = time(NULL);
Sleep(max(1, (lastkoupdatetime - tn + 2) * 1000));
lastkoupdatetime = time(NULL);
MongoUpdates ^mgudt = gcnew MongoUpdates(i, k);
Thread ^updateko = gcnew Thread(gcnew ThreadStart(mgudt, &MongoUpdates::UpdateKO));
updateko->Start();
}
这是 MongoUpdates 中的函数:
void MongoUpdates::UpdateKO {
mongoImp->updateKO(i, k);
}
mongoImp is an instance of the mongoDB C# driver compiled as dll.
下面是 C# 驱动程序中的代码:
public static async void updateKO(int i, int k)
{
await updateKOdr(i, k);
}
static async Task updateKOdr(int i, int k)
{
string col = "ko." + i.ToString();
var collection = _database.GetCollection<BsonDocument>(col);
var builder = Builders<BsonDocument>.Filter;
var filter = builder.Eq("a", i) & builder.Lte("lf", k);
var update = Builders<BsonDocument>.Update.Set("status", 0);
var result = await collection.UpdateOneAsync(filter, update);
}
如果我删除以下部分:
time_t tn = time(NULL);
Sleep(max(1, (lastkoupdatetime - tn + 2) * 1000));
lastkoupdatetime = time(NULL);
如果两个或多个线程同时处理同一个集合,它几乎总是会失败。请帮忙。
我发现问题是我在每次更新操作中都创建了一个新的集合实例。这很糟糕,我没有注意到,因为代码是很久以前我对 mongoDB 还很陌生时编写的。 mongoDB 集合是线程安全的,所以我应该像这样在全局级别定义它:
protected static IMongoCollection<BsonDocument> _collection;
所以我可以使用它而无需每次都创建它的新实例。我只需要这样做:
if (_collection == null) {
_collection = _database.GetCollection<BsonDocument>("ko." + i.ToString());
}