C# c语言中的并行任务与线程安全#

C# c语言中的并行任务与线程安全#,c#,parallel-processing,task-parallel-library,C#,Parallel Processing,Task Parallel Library,我有两个独立的任务和两个独立的操作。我认为t0是线程安全的,但我不确定t1。对吗?并发字典的性能非常糟糕,我需要向集合中插入大量数据 var t0 = new Task[2] { Task.Factory.StartNew(()=> { list1=new sortedlist<int,int>(sortedlist1) } }), Task.Factory.StartNew(()=> { l

我有两个独立的任务和两个独立的操作。我认为t0是线程安全的,但我不确定t1。对吗?并发字典的性能非常糟糕,我需要向集合中插入大量数据

var t0 = new Task[2]
{
    Task.Factory.StartNew(()=>
    {
        list1=new sortedlist<int,int>(sortedlist1)
    }
    }),
    Task.Factory.StartNew(()=>
    {
        list2=new sortedlist<int,int>(sortedlist2)
    })
};
Task.WaitAll(t0)

var t1 = new Task[2]
{
    Task.Factory.StartNew(()=>
    {
        foreach (var item in sortedlist1)
        {
            list1.Add(item.Key, item.Value);
        }
    }),
    Task.Factory.StartNew(()=>
    {
        foreach (var item in sortedlist2)
        {
            list2.Add(item.Key, item.Value);
        }
    })
};
Task.WaitAll(t1)
var t0=新任务[2]
{
Task.Factory.StartNew(()=>
{
列表1=新的分类列表(分类列表1)
}
}),
Task.Factory.StartNew(()=>
{
列表2=新的分类列表(分类列表2)
})
};
Task.WaitAll(t0)
var t1=新任务[2]
{
Task.Factory.StartNew(()=>
{
foreach(分类列表1中的var项目)
{
列表1.Add(item.Key,item.Value);
}
}),
Task.Factory.StartNew(()=>
{
foreach(分类列表2中的var项目)
{
列表2.Add(item.Key,item.Value);
}
})
};
Task.WaitAll(t1)

这似乎没问题-您没有在任务之间访问相同的变量。t1[]中的任务在t0[]中的任务完成之前不会运行

您可以使用Parallel.Do()而不是在数组中创建任务,然后等待它们完成—这使您的意图更加明确,并避免了许多基于数组的仪式


我假设你编了一个例子,而不是实际的代码?

正如所写的,这段代码不起作用。第一对任务中分配的列表不会分配给第二对任务使用的变量。让我们忽略这一点,看看这里的一般概念

这两个列表不必在单独的线程中分配,就可以在单独的线程中使用。而且,您肯定不需要在单独的任务中浪费精力分配每个列表。列表可以由主线程分配,特别是当主线程希望在任务完成后使用列表时。唯一真正的问题是一个列表是否有可能被两个线程同时修改

如果列表1仅由task1读取和写入,而列表2仅由task2读取和写入,则可以在各自任务中对列表执行任何操作,而不会产生任何冲突


使用Task.WaitAll,就像您已经在做的一样,等待两个任务完成。这两个任务完成后,主线程可以控制list1和list2进行进一步修改。在一组并行执行的任务之后,一个常见的后续操作是将多个任务的工作合并到最终输出中。(请参阅“MapReduce”)

任务之间似乎没有任何共同之处。为什么你认为它不是线程安全的?确切地说,我很惊讶,因为在t0中没有数据丢失,但在t1中,我的部分数据丢失,这是一种question@Alex不,不是。SE用于实际工作但可以改进的代码。根据mohammad的解释,这段代码不起作用。虽然t1中的两个操作是独立的,但是在第二个任务中丢失了数据。根据这个解释,您认为多任务在这种情况下没有用处,我应该使用顺序编程。因为我认为如果我使用多任务来填充列表,速度会提高。我说分配列表对象不需要多任务。并行地向多个独立列表执行list.add()可能有价值。完成后,您将拥有来自N个任务的N个列表。然后呢?当您需要在列表中查找某些内容时,是否打算执行N次查找?可能不会。一种常见的模式是在所有任务完成后将多个任务的输出合并到一个列表中。这是“mapreduce”模式。处理多个线程/任务时需要注意的一点是,您需要确保分配给每个线程的工作量足够大,足以证明使用多个线程所需的人力和机器成本。我在静态方法中编写了此代码,该方法返回一个包含2个排序列表的类变量。