首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >多线程向List<List<string>>提供数据的多线程;多线程

多线程向List<List<string>>提供数据的多线程;多线程
EN

Stack Overflow用户
提问于 2012-09-06 20:02:19
回答 3查看 2K关注 0票数 1

我有多个线程创建一个public List<List<String>> listOfLists并用数据填充它。在完成所有线程之后,我想使用list.AddRange()组合主线程的listOfLits中的多个线程中的所有这些列表。

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

如果我为static使用listOfLists关键字,它就能很好地工作。我想做的就是让static.摆脱

下面是一个小小的例子。

  1. 我创建了一个简单的Person对象(主线程)
  2. 主线程调用一个方法来创建3个线程。
  3. 每个线程都调用另一个方法来用数据填充自己的listOfLists
  4. 在该方法的末尾,我将线程拥有的listOfLists添加到static listOfLists中。
  5. 这就是我想要避免的。不能有任何静电。
  6. 我只想在我的主线程中获得这些线程数据,并在主线程上继续执行应用程序。

编辑:必须是.NET 3.5

Edit2:一种解决方案似乎是在启动线程时将listOfLists (主线程)的引用作为参数提供。还有其他方法来解决这样的线程问题吗?

代码语言:javascript
复制
namespace Threading
{
    class Program
    {
        static void Main(string[] args)
        {
            Person p = new Person("mainThread");
            p.startMultiThreading();
        }                   
 }

代码语言:javascript
复制
class Person
{
    public String name;
    public List<String> privatePet;
    public List<List<String>> listOfLists = new List<List<string>>();
    public static List<List<String>> familyPets = new List<List<string>>();

    public Person(String n) { name = n; } //constructor
    public Person() { }

    public void startMultiThreading()
    {
        List<Thread> list_threads = new List<Thread>();
        for (int i = 0; i < 3; i++)
        {
            Person multiThreadPerson = new Person("multi: " + i); //create new Person
            Thread t = new Thread(multiThreadPerson.fill_List); //create new Thread
            t.Name = multiThreadPerson.name; //name the Thread with PersonName

            list_threads.Add(t);
            list_threads[i].Start(); //new Person is calling fill_list()
        }

        for (int i = 0; i < list_threads.Count; i++)
        {
            list_threads[i].Join();
        }

        familyPets.Add(new List<string>{"this is mainthread again"});
        foreach (List<String> list in familyPets)
        {
            list.ForEach(e => Debug.WriteLine(e));
        }
    }

    public void fill_List()
    {
        privatePet = new List<string>();
        lock (familyPets)
        {
            for (int i = 0; i < 20; i++)
            {
                privatePet.Add("dog :" + Thread.CurrentThread.Name);
                privatePet.Add("cat :" + this.name);
                listOfLists.Add(privatePet);
            }
            familyPets.AddRange(listOfLists); //adding up all listOfLists to the mainthread listOfLists
        }//lock 
    }
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-09-06 21:06:32

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

还要注意的是,您的锁定非常广泛,以至于只允许一个这样的线程执行任何操作,从而击败了多线程。您希望它们只处理它们能够处理的事情(例如,本例中的privatePet,以及i ),因为每个线程都有各自的视图。Thread.CurrentThread是静态的,但线程是安全的(否则它是没有意义的),虽然this不是线程安全的,并且是共享的,但是在一个字符串字段中读取多个线程,而没有线程正在写入它,这是安全的(您可以通过使name readonly变得更加安全,就像您可以100%自信地查看那些代码,它不会被写到它,除非它不顾一切地处理事情。)

代码语言:javascript
复制
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
    } 
}

然后,在调用方法中,设置列表并将其传递到start中。

代码语言:javascript
复制
list_threads[i].Start(whateverTheListIsCalled);
票数 1
EN

Stack Overflow用户

发布于 2012-09-06 21:05:55

我认为问题在于您使用同一个类"Person“来填充数据和连接数据。

代码语言:javascript
复制
Person p = new Person("mainThread");

从来不调用fill_List(),也不使用变量privatePet和listOfLists。

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

代码语言:javascript
复制
public Person(String n, List<List<String>> pRefFamilyPets) { name = n; familyPets = pRefFamilyPets; } //constructor

并覆盖这一行,添加familyPets引用

代码语言:javascript
复制
Person multiThreadPerson = new Person("multi: " + i, familyPets); //create new Person

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

票数 0
EN

Stack Overflow用户

发布于 2012-09-07 07:56:45

代码语言:javascript
复制
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();

或将清单合并:

代码语言:javascript
复制
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());

阅读任务,并在MSDN上并行。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12307524

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档