Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 调用相同方法的并发线程会导致ConcurrentBag中出现重复的线程<;数据行>;收集_C#_Multithreading_Concurrency_Duplicates - Fatal编程技术网

C# 调用相同方法的并发线程会导致ConcurrentBag中出现重复的线程<;数据行>;收集

C# 调用相同方法的并发线程会导致ConcurrentBag中出现重复的线程<;数据行>;收集,c#,multithreading,concurrency,duplicates,C#,Multithreading,Concurrency,Duplicates,我必须在一个线程上处理一个大数据集,这需要一个多小时。我已经实现了一些多线程来加速这个过程。每个线程都处理特定范围的数据,没有重叠,但当它们将结果插入到我创建的ConcurrentBag集合中时,会出现一些重复 这怎么可能?任何关于我可以做得更好的建议都将不胜感激 主要方法: public static ConcurrentBag<DataRow> finalRowList = new ConcurrentBag<DataRow>(); //Create a concur

我必须在一个线程上处理一个大数据集,这需要一个多小时。我已经实现了一些多线程来加速这个过程。每个线程都处理特定范围的数据,没有重叠,但当它们将结果插入到我创建的
ConcurrentBag
集合中时,会出现一些重复

这怎么可能?任何关于我可以做得更好的建议都将不胜感激

主要方法:

public static ConcurrentBag<DataRow> finalRowList = new ConcurrentBag<DataRow>(); //Create a concurrent collection of datarows so we can thread these calculations
public static DataTable results = new DataTable(); //Final datatable the datarows are added to

static void Main(string[] args)
{
//The goal is to calculate correlation between each item in list 1 against each item in list 2
List<string> Variable1List = populateVariable1List(); //Primary List of distinct items to iterate over
List<string> Variable2List = populateVariable2List(); //Secondary list of distinct items

DateTime endDate = new DateTime(2020, 3, 31);

//Separate threads based on alphabetic ranges so there is no overlap
Thread t1 = new Thread(() => CalculatePairCorrelation(Variable1List.Where(s => string.Compare(s, "G") < 0), Variable2List, endDate));
Thread t2 = new Thread(() => CalculatePairCorrelation(Variable1List.Where(s => string.Compare(s, "G") >= 0 && string.Compare(s, "M") < 0), Variable2List, endDate));
Thread t3 = new Thread(() => CalculatePairCorrelation(Variable1List.Where(s => string.Compare(s, "M") >= 0 && string.Compare(s, "S") < 0), Variable2List, endDate));
Thread t4 = new Thread(() => CalculatePairCorrelation(Variable1List.Where(s => string.Compare(s, "S") >= 0), Variable2List, endDate));

List<Thread> threads = new List<Thread>();
threads.Add(t1);
threads.Add(t2);
threads.Add(t3);
threads.Add(t4);

foreach (Thread t in threads)
{
    t.Start();
}

foreach (Thread t in threads)
{
    t.Join();
}

//Add rows from finalRowList to final datatable
foreach (var dr in finalRowList)
{
    results.Rows.Add(dr);
}
}
public static ConcurrentBag finalRowList=new ConcurrentBag()//创建数据行的并发集合,以便我们可以执行这些计算
公共静态数据表结果=新数据表()//将数据行添加到的最终数据表
静态void Main(字符串[]参数)
{
//目标是计算列表1中每个项目与列表2中每个项目之间的相关性
List Variable1List=populateVariable1List();//要迭代的不同项的主列表
List Variable2List=populateVariable2List();//不同项的二级列表
DateTime endDate=新的日期时间(2020,3,31);
//根据字母范围分开线程,因此没有重叠
线程t1=新线程(()=>CalculatePairCorrelation(Variable1List.Where(s=>string.Compare(s,“G”)<0),Variable2List,endDate));
线程t2=新线程(()=>CalculateAirCorrelation(Variable1List.Where(s=>string.Compare(s,“G”)>=0&&string.Compare(s,“M”)<0),Variable2List,endDate));
线程t3=新线程(()=>CalculateAirCorrelation(Variable1List.Where(s=>string.Compare(s,“M”)>=0&&string.Compare(s,“s”)<0),Variable2List,endDate));
线程t4=新线程(()=>CalculatePairCorrelation(Variable1List.Where(s=>string.Compare(s,“s”)>=0),Variable2List,endDate));
列表线程=新列表();
添加(t1);
添加(t2);
添加(t3);
添加(t4);
foreach(螺纹中的螺纹t)
{
t、 Start();
}
foreach(螺纹中的螺纹t)
{
t、 Join();
}
//将finalRowList中的行添加到最终数据表
foreach(最终列表中的var dr)
{
结果.行.添加(dr);
}
}
CalculatePairCorrelation()代码:

publicstaticvoidcalculateAirCorrelation(IEnumerablest1、IEnumerablest2、DateTime endDate、int行)
{
foreach(列表1中的变量项1)
{
foreach(列表2中的变量项2)
{                
double r10=计算相关性(第1项、第2项、结束日期、第10项);
双r30=计算相关性(第1项、第2项、结束日期,30);
var dr=results.NewRow();
dr[“Item1”]=Item1;
dr[“项目2”]=项目2;
dr[“R10”]=R10;
dr[“R30”]=R30;
finalRowList.Add(dr);//添加到线程安全集合
}
}
}

问题可能与这一行有关,这一行在并行路径中被称为:

var dr = results.NewRow();
创建
DataRow
可能会变异底层
DataTable
,这不是线程安全类

我的建议是远离并发收集和数据的手动分区,而是使用易于使用且更难出错的方法:

var resultsList = Variable1List
    .SelectMany(_ => Variable2List, (Item1, Item2) => (Item1, Item2))
    .AsParallel()
    .AsOrdered() // Optional
    .WithDegreeOfParallelism(4) // Optional
    .Select(pair => (
        Item1: pair.Item1,
        Item2: pair.Item2,
        R10: CalculateCorrelation(pair.Item1, pair.Item2, endDate, 10),
        R30: CalculateCorrelation(pair.Item1, pair.Item2, endDate, 30)
    ))
    .ToList();

foreach (var result in resultsList)
{
    var dr = results.NewRow();
    dr["Item1"] = result.Item1;
    dr["Item2"] = result.Item2;
    dr["R10"] = result.R10;
    dr["R30"] = result.R30;
    results.Rows.Add(dr);
}

若你们有DUP,首先要寻找的是一种分裂机制。您应该使用队列,您的问题将得到解决。您可以再详细说明一下吗?您可以创建膨胀收集队列,并在一个线程中执行
任务。运行(()=>{加载您的队列})
。然后创建1-n个使用者线程
任务。运行(()=>{get from queue and process})
。等待结束
任务。等待(生产者、消费者1、消费者2等)
这保证了您快速可靠的多线程处理我为Item1列表实现了一个全局
ConcurrentQueue
,并为每个线程实现了Item2列表的一个新实例。我仍然有同样数量的副本。我需要进一步挖掘…我认为创建datarow只是创建一个与表具有相同模式的新行。我不知道它实际上会改变桌子。我会给你一个机会,然后再报告。并行的唯一问题是,你没有太多的控制权。你永远不知道有多少线程在运行。@eek你是对的。创建新行不会将此行添加到表中,这是
DataTable.NewRow
方法的源代码。通过快速查看,它似乎确实改变了类的内部状态。您正确地认为NewRow()调用不是线程安全的!我更改了代码以生成一个空行的并发集合,然后在填充每一行时执行TryTake()。谢谢
var resultsList = Variable1List
    .SelectMany(_ => Variable2List, (Item1, Item2) => (Item1, Item2))
    .AsParallel()
    .AsOrdered() // Optional
    .WithDegreeOfParallelism(4) // Optional
    .Select(pair => (
        Item1: pair.Item1,
        Item2: pair.Item2,
        R10: CalculateCorrelation(pair.Item1, pair.Item2, endDate, 10),
        R30: CalculateCorrelation(pair.Item1, pair.Item2, endDate, 30)
    ))
    .ToList();

foreach (var result in resultsList)
{
    var dr = results.NewRow();
    dr["Item1"] = result.Item1;
    dr["Item2"] = result.Item2;
    dr["R10"] = result.R10;
    dr["R30"] = result.R30;
    results.Rows.Add(dr);
}