C#更新不同类中的字典

时间:2016-03-14 21:01:30

标签: c# multithreading class dictionary networking

我有一个包含数据的字典,我有处理并发客户端请求的线程。我希望一些客户端请求在需要时更改字典中的值,但不确定如何在处理线程和类时修复范围问题。

我尝试做的一个简单示例如下:

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类中更改字典(需要所有线程都可以访问)?

我不知道如何索引线程或者至少在字典条目中标记它们。我无法找到将特定值发送到特定线程的方法。

2 个答案:

答案 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;这里