我有一个包含数据的字典,我有处理并发客户端请求的线程。我希望一些客户端请求在需要时更改字典中的值,但不确定如何在处理线程和类时修复范围问题。
我尝试做的一个简单示例如下:
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类中更改字典(需要所有线程都可以访问)?
我不知道如何索引线程或者至少在字典条目中标记它们。我无法找到将特定值发送到特定线程的方法。
答案 0 :(得分: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参数更新现有条目。
共享属性的其他选项可以是静态类或单例。您可能需要考虑将使用此属性和当前体系结构的内容,以查看将其插入的位置。
答案 1 :(得分:-1)
您可以将字典作为参数放在start函数中,如:
Twrite_analysis(cout, "median", Tanalysis(grade_aux, did), Tanalysis(grade_aux, didnt));
https://msdn.microsoft.com/en-us/library/6x4c42hc%28v=vs.110%29.aspx
重要的是使用引用调用,以便您可以访问相同的字典而不是副本。但我不确定编译器是否会接受&#39; ref&#39;这里