2016-03-14 76 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'