我有一本包含数据的字典,还有处理并发客户端请求的线程。我希望一些客户端请求在需要时更改字典中的值,但不确定在处理线程和类时如何修复范围问题。
下面是我想要做的一个简单的例子:
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类中的字典(它需要所有线程都可以访问)?
我不知道如何在字典条目中索引线程,或者至少标记它们。我很难找到将特定值发送到特定线程的方法。
发布于 2016-03-14 21:31:03
从.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更新现有条目。
共享该属性的其他选项将通过静态类或单例进行。您可能需要考虑将使用此属性的是什么,以及当前的体系结构,以查看将其放入何处。
发布于 2016-03-14 21:10:16
您可以将字典作为参数放在start函数中,如下所示:
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”
https://stackoverflow.com/questions/35997994
复制相似问题