0

我正在使用C++/Cli與mongoDB最新的C#驅動程序一起編譯爲dll。我在C++代碼中使用了驅動程序的一個實例。爲什麼要在全局級別定義mongoDB集合 - 它是線程安全的

我已經嘗試了很多次。如果我構建多個線程,每個線程都試圖更新同一個集合中的文檔,似乎只有一個線程會成功。當我爲線程設置睡眠時間時,它似乎工作正常。但是我需要在短時間內同時更新數千個文檔,因此設置睡眠時間不是一種有效的方法。

下面是該線程是如何開始:

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); 

如果兩個或多個線程同時在同一個集合上工作,它幾乎總是會失敗。請幫忙。

回答

0

我想出問題是我在每次更新操作中都創建了一個新的集合實例。這很糟糕,我沒有注意到,因爲代碼是很早以前寫的,當時我對mongoDB還很陌生。 MongoDB的集合是線程安全的,所以我要在全球層面上定義它是這樣的:

protected static IMongoCollection<BsonDocument> _collection; 

所以我可以使用它,而無需創建它的每一次一個新的實例。我只需要這樣做:

if (_collection == null) { 
    _collection = _database.GetCollection<BsonDocument>("ko." + i.ToString()); 
} 
相關問題