正如我在標題中所說,我需要使用字典來模擬 ConcurrentDictionary,因為我需要序列化所述集合并且并發變體不可序列化。關于 ConcurrentDictionary 如何處理多執行緒以及我應該如何實作它的任何想法?
我還沒試過,感覺就像一條離開水的魚。
uj5u.com熱心網友回復:
BinaryFormatter序列化被認為是過時的。嘗試改用 Json 序列化:
ConcurrentDictionary<string, Variant> dict = new ConcurrentDictionary<string, Variant>();
dict.TryAdd("one", new Variant() { Name = "one", Coordinate = new System.Drawing.Point() { } });
dict.TryAdd("two", new Variant() { Name = "two", Coordinate = new System.Drawing.Point() { } });
var serialized = JsonConvert.SerializeObject(dict);
//This works just fine
var deserialized = JsonConvert.DeserializeObject<ConcurrentDictionary<string, Variant>>(serialized);
然后,您可以將其保存string在您選擇的存盤中。你的資料結構是未知的,所以我只是為了說明目的而編造了一些東西。
您將不得不擔心的一件事是鎖定序列化方法,因為您嘗試每秒執行幾次。如果您將其保存到磁盤,您可能會遇到檔案鎖定問題等等。出于這個原因,你也應該重新考慮你的狀態保存策略。
類似于以下內容:
private ConcurrentDictionary<string, Variant> _history = new ConcurrentDictionary<string, Variant>();
//Somewhere in your code you populate the dictionary
_history.TryAdd("one", new Variant() { Name = "one", Coordinate = new System.Drawing.Point() { } });
_history.TryAdd("two", new Variant() { Name = "two", Coordinate = new System.Drawing.Point() { } });
private object _lock = new object();
private void SaveHistory()
{
lock (_lock)
{
var serialized = JsonConvert.SerializeObject(_history);
DataLayer.SaveHistory(serialized);
}
}
private void RestoreHistory()
{
lock (_lock)
{
var serialized = DataLayer.GetHistory();
_history = JsonConvert.DeserializeObject<ConcurrentDictionary<string, Variant>>(serialized);
}
}
uj5u.com熱心網友回復:
由于評論指定這是為了保存回放。
更好的方法可能是讓主執行緒或擁有要保存的資料的任何執行緒創建資料的副本并將其放入緩沖區中。這個緩沖區可以保存在記憶體中,也可以與游戲同時寫入磁盤。
這樣可以避免阻塞主游戲回圈的任何風險,并保證獲得一致的資料。您還可以添加功能,例如每第 n 幀保存資料,或在緩沖區已滿時跳過資料保存。
我實作這一點的方式是使用concurrentQueue。創建一個回圈運行的長時間運行的任務myQueue.GetConsumingEnumerable(),并確保在CompleteAdding完成后呼叫。但是像DataFlow這樣的東西也可能是一種選擇。
您很可能還應該避免使用 BinaryFormatter,如果速度是一個問題,我可能會使用帶有 SerializeWithLengthPrefix 方法的Protobuf .net ,這樣您就可以將多個獨立物件寫入同一個流。
uj5u.com熱心網友回復:
您可以使用lock陳述句來保護對 的訪問,Dictionary并確保一次只有一個執行緒會這樣做。您可以創建一個物件來鎖定,例如
private object syncRoot = new object();
然后鎖定它:
lock (syncRoot)
{
// Only one thread will be able to execute here at a time.
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/526722.html
標籤:C#字典并发线程安全
下一篇:對于可以在每個代碼區宣告的變數
