C# 多个线程向列表提供数据<;列表<;字符串>&燃气轮机;到主线程;多线程

C# 多个线程向列表提供数据<;列表<;字符串>&燃气轮机;到主线程;多线程,c#,multithreading,list,concurrency,.net-3.5,C#,Multithreading,List,Concurrency,.net 3.5,我有多个线程创建一个公共列表列表,并用数据填充它。完成所有线程后,我想使用list.AddRange()组合主线程的listOfLits中多个线程的所有列表 因此,如果我有三个线程,每个线程的listOfLists有10个元素,那么主线程的listOfLists将有30个元素。只需简单地添加它们,mainthread对象就必须有线程插入的所有数据 如果我在列表中使用静态关键字,它将非常有效。我想做的就是摆脱static 这里有一个小例子 我创建了一个简单的Person对象(主线程) 主线程调用一

我有多个线程创建一个
公共列表列表
,并用数据填充它。完成所有线程后,我想使用
list.AddRange()
组合主线程的
listOfLits
中多个线程的所有列表

因此,如果我有三个线程,每个线程的
listOfLists
有10个元素,那么主线程的
listOfLists
将有30个元素。只需简单地添加它们,mainthread对象就必须有线程插入的所有数据

如果我在
列表
中使用
静态
关键字,它将非常有效。我想做的就是摆脱
static

这里有一个小例子

  • 我创建了一个简单的Person对象(主线程)
  • 主线程调用一个方法来创建3个线程
  • 这些线程中的每一个都调用另一个方法,用数据填充自己的
    listOfLists
  • 在该方法的末尾,我将线程自己的
    listOfLists
    添加到
    静态listOfLists
  • 这就是我想要避免的。不得有任何静电干扰
  • 我只想让这些线程数据在我的主线程中可用,并在主线程上继续应用程序
  • 编辑:它必须是.NET3.5

    Edit2:一种解决方案似乎是在启动线程时提供(主线程的)ListofList的引用作为参数。有没有其他方法可以解决这样的线程问题



    班级人员
    {
    公共字符串名称;
    公开名单私人宠物;
    公共列表listOfLists=新列表();
    public static List familyPets=new List();
    公共人物(字符串n){name=n;}//构造函数
    公众人物(){}
    public void startMultiThreading()
    {
    List_threads=新列表();
    对于(int i=0;i<3;i++)
    {
    Person多线程Person=newperson(“multi:+i);//创建新的Person
    Thread t=新线程(multiThreadPerson.fill_List);//创建新线程
    t、 Name=multiThreadPerson.Name;//用PersonName命名线程
    列出所有线程。添加(t);
    list_threads[i].Start();//新用户正在调用fill_list()
    }
    对于(int i=0;iDebug.WriteLine(e));
    }
    }
    公共空白填写清单()
    {
    privatePet=新列表();
    锁(家庭型)
    {
    对于(int i=0;i<20;i++)
    {
    添加(“dog:+Thread.CurrentThread.Name”);
    privatePet.Add(“cat:+this.name”);
    添加(私人宠物);
    }
    familyPets.AddRange(ListofList);//将所有ListofList添加到主线程ListofList
    }//锁
    }
    }
    
    我认为问题在于,填充数据和加入数据都使用同一类“Person”

    Person p = new Person("mainThread");
    
    从不调用fill_List(),也不使用变量privatePet和listofList

    在不过度修改代码的情况下,一个简单的解决方案是添加一个新的构造函数:

    public Person(String n, List<List<String>> pRefFamilyPets) { name = n; familyPets = pRefFamilyPets; } //constructor
    

    我无法遵循逻辑,但这似乎避免了使用STATIC,因为您正在将引用传递给其他线程。

    我认为问题在于您在填充数据和连接数据时使用了相同的类“Person”

    Person p = new Person("mainThread");
    
    从不调用fill_List(),也不使用变量privatePet和listofList

    在不过度修改代码的情况下,一个简单的解决方案是添加一个新的构造函数:

    public Person(String n, List<List<String>> pRefFamilyPets) { name = n; familyPets = pRefFamilyPets; } //constructor
    

    我无法遵循逻辑,但这似乎避免了使用STATIC,因为您正在将引用传递给其他线程。

    以及
    ThreadStart
    委托,您可以使用
    参数化ThreadStart
    委托创建线程,然后
    Start()
    带有一个重载,该重载接受单个对象参数。您可以使用需要传递到线程的delgate的任何信息创建该对象,在本例中,delgate只是您所关心的列表的单个列表

    还要注意的是,您的锁定太宽了,以至于只允许一个这样的线程执行任何操作,从而击败了多线程。您希望他们自己处理只有他们才能处理的事情(
    privatePet
    ,例如,在本例中,
    i
    ,因为每个线程都有自己的独立视图。
    thread.CurrentThread
    是静态的,但线程是安全的(否则将毫无意义)虽然
    这个
    不是线程安全的,是共享的,但是在零线程写入字符串字段时,让多个线程从字符串字段中读取是安全的(您可以通过将
    名称
    设置为只读
    使其更加安全,因为这样您就可以100%放心地知道,只要查看该代码,就不会有任何内容写入它,除非它故意弄乱东西

    public void fill_List(object targetList)
    {
        List<List<String>> familyPets = (List<List<String>>)targetList;
        List<List<String>> listOfLists = new List<List<String>>();//we'll use our own local one of these thanks, as it's just this thread's concern write now.
        privatePet = new List<string>();
        for (int i = 0; i < 20; i++)
        {
            privatePet.Add("dog :" + Thread.CurrentThread.Name);
            privatePet.Add("cat :" + this.name);
            listOfLists.Add(privatePet);
        }
        //note you don't need to lock until you are doing something
        //that hits on something that other threads might hit on.
        //otherwise you've just got each thread locked for their entire
        //duration and you might as well just do the whole thing
        //in one thread.
        lock (familyPets)
        {
            familyPets.AddRange(listOfLists); //adding up all listOfLists to the mainthread listOfLists
        } 
    }
    

    除了
    ThreadStart
    委托外,您还可以使用
    ParameterizedThreadStart
    委托创建线程,然后使用
    Start()
    带有一个重载,该重载接受一个对象参数。您可以使用需要传递到线程的delgate中的任何信息创建该对象,在本例中,delgate只是您所关心的列表的单个列表

    还请注意,您的锁定范围太广,以至于只能让一个这样的线程执行任何操作,从而破坏了多线程。您希望他们自己处理只有他们才能处理的事情(
    privatePet
    ,例如,在本例中,
    i
    ,因为每个线程都有自己的独立视图。
    thread.CurrentThr
    
    public void fill_List(object targetList)
    {
        List<List<String>> familyPets = (List<List<String>>)targetList;
        List<List<String>> listOfLists = new List<List<String>>();//we'll use our own local one of these thanks, as it's just this thread's concern write now.
        privatePet = new List<string>();
        for (int i = 0; i < 20; i++)
        {
            privatePet.Add("dog :" + Thread.CurrentThread.Name);
            privatePet.Add("cat :" + this.name);
            listOfLists.Add(privatePet);
        }
        //note you don't need to lock until you are doing something
        //that hits on something that other threads might hit on.
        //otherwise you've just got each thread locked for their entire
        //duration and you might as well just do the whole thing
        //in one thread.
        lock (familyPets)
        {
            familyPets.AddRange(listOfLists); //adding up all listOfLists to the mainthread listOfLists
        } 
    }
    
    list_threads[i].Start(whateverTheListIsCalled);
    
    Enumerable.Range(0, 3).AsParallel().WithDegreeOfParallelism(3).Select(n => {
        var list = new List<string>();
        list.Add(n + ": One");
        list.Add(n + ": Two");
        list.Add(n + ": Three");
        return list;
    }).ToList();
    
    Enumerable.Range(0, 3).AsParallel().WithDegreeOfParallelism(3).Select(n => {
        var list = new List<string>();
        list.Add(n + ": One");
        list.Add(n + ": Two");
        list.Add(n + ": Three");
        return list;
    }).Aggregate((a, b) => a.Union(b).ToList());