为什么我应该在全局级别定义 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());
}