2016-03-14 80 views
0

我有一個字典,其中包含數據,我有處理併發客戶端請求的線程。我希望某些客戶端請求在需要時更改字典中的值,但不知道在處理線程和類時如何解決範圍問題。C#更新字典在不同的類

的什麼,我試圖做一個簡單的例子如下:

class Program 
{ 
    public static Dictionary<string, int> teamInformation = new Dictionary<string, int>(); 

static void Main(string[] args) 
{ 
    runserver(); 
} 

static void runServer() 
{ 
    //connection stuff 

    while(true) 
    { 
     threadRequest = new Handler(); 
     Thread t = new Thread (() => threadRequest.clientInteraction(connection)); 
     t.Start(); 
    } 
} 

class Handler 
{ 
    public void clientInteraction(Socket connection) 
    { 
     //does stuff 

     teamInformation.Add(pTeamName, 0); //where pTeamName has been read from the client input 
    } 
} 

我怎麼會去結交Handler類更改詞典(這需要所有線程可訪問)?

我不知道如何爲線索編制索引或者至少在詞典條目中標記它們。我很難找出將特定值發送到特定線程的方法。

+1

使用[ConcurrentDictionary](https://msdn.microsoft.com/zh-cn/library/dd287191( v = vs.110).aspx) – stuartd

+0

@stuartd這似乎正是我需要感謝。我現在正在研究它。但是我是否需要每次在Handler類中聲明Concurrent Dictionary?是否會爲所有線程編輯具有相同名稱的字典?或者只是簡單地創建與每個線程相關的多個併發字典 – James

回答

2

從.NET 4.0集合開始,可以更好地處理線程安全問題。你可以有許多線程寫入他們沒有問題。 (https://msdn.microsoft.com/en-us/library/dd997305(v=vs.110).aspx)。多個讀者也是如此。

問題在於,當通過獲取修改的集合枚舉來同時發生這兩個操作時,問題就在於此。

更好的選擇是使用支持線程安全的數據類型,例如線程安全的ConcurrentDictionary,並允許讀者和作者同時進行。 (不包括通過ConcurrentDictionary實現的接口訪問的一些成員)。

的變化是最有可能在變化的下降對你: public static Dictionary<string, int> teamInformation = new Dictionary<string, int>();public static ConcurrentDictionary<string, int> teamInformation = new ConcurrentDictionary<string, int>();

更大的深度

編輯見https://msdn.microsoft.com/en-us/library/dd287191(v=vs.110).aspx:這裏是它的一個例子是使用:

using System; 
using System.Collections.Concurrent; 
using System.Threading; 

namespace SO 
{ 
    public class Program 
    { 
     public static ConcurrentDictionary<string, int> teamInformation = new ConcurrentDictionary<string, int>(); 

     static void Main(string[] args) 
     { 
      Start(); 

      Console.WriteLine("ConcurrentDictionary contains : " + teamInformation.Count); 
      Console.ReadKey(); 
     } 

     static void Start() 
     { 
      for (var i = 0; i < 10; i++) 
      { 
       var threadRequest = new Handler(); 
       var thread = new Thread(() => threadRequest.ClientInteraction(teamInformation)); 
       thread.Start(); 
      } 
     } 
    } 

    public class Handler 
    { 
     public void ClientInteraction(ConcurrentDictionary<string, int> teamInformation) 
     { 
      for (var i = 0; i < 10; i++) 
      { 
       teamInformation.AddOrUpdate(Guid.NewGuid().ToString(), i, (key, val) => val); 
      } 
     } 
    } 
} 

由於ConcurrentDictionary是線程安全的,你可以直接將它傳遞給你的線程。這段代碼只是產生一個線程負載併爲每個線程創建一個新條目。

但是,通過使用AddOrUpdate,您可以指定如果您的密鑰(或團隊)存在,則可以使用第三個Func參數更新現有條目。

共享屬性的其他選項將通過靜態類或單例。您可能需要考慮將使用此屬性和您當前的體系結構來查看將其插入的位置。

+0

我看到在使用線程時如何使用併發字典更好,並且更新了我的代碼,因此非常感謝您的提示!不過,我現在正在努力瞭解在哪裏聲明新的字典。在嘗試在Handler類中添加值時,用併發字典強制替換舊字典仍會標記範圍問題。 Good ol'「字典在當前上下文中不存在」。 – James

+0

我已經用示例顯示了實現代碼的一種方式更新了我的答案。 –

-1

你可以把字典作爲放慢參數在啓動功能,如:

Thread t = new Thread (() => threadRequest.clientInteraction(connection)); 
    t.Start(ref teamInformation); 

https://msdn.microsoft.com/en-us/library/6x4c42hc%28v=vs.110%29.aspx

重要的是通過參考使用電話,所以你可以訪問相同的單詞,而不是一個副本。但我不知道編譯器是否會接受這裏的'ref'