c#删除元素后的Parallel For Loop索引异常
c# Parallel For Loop index exceptions after removing the element
在我的算法中,我要做的是跟随。
while (R.Count > 0)
{
//R is also List<string>()
var N = new List<string>();
var first = R[0];
N.Add(first);
R.Remove(first);
//below commented code runs just fine but it takes a lot of time that is why i need to do multithreading to make it faster
//for (int i = R.Count - 1; i >= 0; i--)
//{
// if (hamming(first, R[i]))
// { //hamming is a function just compare two strings and returns true or false.
// N.Add(R[i]);
// R.RemoveAt(i);
// }
//}
//Below is code of my attempt of multithreading the loop. I have tried it with foreach loop as well and it gives same error 'index out of range or argument exception'
//ATTEMPT 1 :-
Parallel.For(0,R.Count, i =>
{
if (hamming(first, R[i]))
{
N.Add(R[i]);
R.RemoveAt(i);
}
});
//ATTEMPT 2 :-
Parallel.For(0,R.Count, i =>
{
if (hamming(first, R[i]))
{
N.Add(R[i]);
R[i]="";
}
});
var K = R.Where(a => a == "").ToList();
var nc = cou - N.Count;
//the value of 'K.Count' and 'nc' should be same here but I have checked in debugger its not the same.
N_Total.Add(N);//this is just a List<List<string>>
}
代码很容易解释,但我仍将尝试在这里进一步阐述。
基本上我需要 运行 这个算法并比较代码中显示的值,如果 hamming returns true 我必须将该值添加到 'N' 并将其从 'R',我必须删除它,因为下次外层 while 循环 运行s List 'R' 应该更小,并且只有那些不满足汉明条件的值应该出现在 R 中在循环的前一个 运行 中。
如果有人需要了解更多,我可以进一步详细说明。
我想要的是以某种多线程方式实现这个目标并且 index out of range
或 Argument exceptions
.
没有例外
非常感谢。
首先 List<string>
不是 ThreadSafe
这意味着它根本不应该用于并行操作。
试试看:ConcurrentBag<string>
。
ConcurentBag
存在于 System.Collections.Concurrent
命名空间中,其中包含更多的线程安全集合。
另一件事是:
您想在对该索引进行任何操作之前确定该索引是否存在。
ConcurentBag
可能有一些限制,也许值得检查该命名空间中的其他集合:System.Collections.Concurrent
因为它们是 ThreadSafe
.
https://msdn.microsoft.com/en-us/library/system.collections.concurrent.aspx
在 R
上使用 Parallel.Foreach
。 Parallel.Foreach 会将您的列表拆分为更小的块并开始处理它们。因此来自不同线程的索引不会相互冲突。
对于 N
你将使用 ConcurrentBag
而不是 List
因为它是线程安全的。这意味着当两个线程碰巧将物品添加到您的包中时,不会发生奇怪的事情。
如果您删除 Parallel 中的项目,您应该通知所有线程新的更改,这将很难(而且非常难看)实施。
List<string> R = new List<string>();
while (R.Count > 0)
{
var removing = new ConcurrentBag<long>();
var N = new ConcurrentBag<string>();
var first = R[0];
N.Add(first);
R.Remove(first);
Parallel.ForEach(R, (item, state, index) =>
{
if(hamming(first, item))
{
N.Add(item);
R[(int)index] = null; // mark as null and ignore.
// this is not thread safe for versioning of list but doesn't matter.
// for R ConcurrentBag can be used too but it doesn't change results after all.
}
});
// now we are safe to reorganize our collection.
R = R.Where(str => str != null).ToList(); // parallel execution doesn't help. see comments below.
// for very large collection this will finish in few milliseconds.
// get other stuff...
}
在我的算法中,我要做的是跟随。
while (R.Count > 0)
{
//R is also List<string>()
var N = new List<string>();
var first = R[0];
N.Add(first);
R.Remove(first);
//below commented code runs just fine but it takes a lot of time that is why i need to do multithreading to make it faster
//for (int i = R.Count - 1; i >= 0; i--)
//{
// if (hamming(first, R[i]))
// { //hamming is a function just compare two strings and returns true or false.
// N.Add(R[i]);
// R.RemoveAt(i);
// }
//}
//Below is code of my attempt of multithreading the loop. I have tried it with foreach loop as well and it gives same error 'index out of range or argument exception'
//ATTEMPT 1 :-
Parallel.For(0,R.Count, i =>
{
if (hamming(first, R[i]))
{
N.Add(R[i]);
R.RemoveAt(i);
}
});
//ATTEMPT 2 :-
Parallel.For(0,R.Count, i =>
{
if (hamming(first, R[i]))
{
N.Add(R[i]);
R[i]="";
}
});
var K = R.Where(a => a == "").ToList();
var nc = cou - N.Count;
//the value of 'K.Count' and 'nc' should be same here but I have checked in debugger its not the same.
N_Total.Add(N);//this is just a List<List<string>>
}
代码很容易解释,但我仍将尝试在这里进一步阐述。
基本上我需要 运行 这个算法并比较代码中显示的值,如果 hamming returns true 我必须将该值添加到 'N' 并将其从 'R',我必须删除它,因为下次外层 while 循环 运行s List 'R' 应该更小,并且只有那些不满足汉明条件的值应该出现在 R 中在循环的前一个 运行 中。
如果有人需要了解更多,我可以进一步详细说明。
我想要的是以某种多线程方式实现这个目标并且 index out of range
或 Argument exceptions
.
非常感谢。
首先 List<string>
不是 ThreadSafe
这意味着它根本不应该用于并行操作。
试试看:ConcurrentBag<string>
。
ConcurentBag
存在于 System.Collections.Concurrent
命名空间中,其中包含更多的线程安全集合。
另一件事是:
您想在对该索引进行任何操作之前确定该索引是否存在。
ConcurentBag
可能有一些限制,也许值得检查该命名空间中的其他集合:System.Collections.Concurrent
因为它们是 ThreadSafe
.
https://msdn.microsoft.com/en-us/library/system.collections.concurrent.aspx
在 R
上使用 Parallel.Foreach
。 Parallel.Foreach 会将您的列表拆分为更小的块并开始处理它们。因此来自不同线程的索引不会相互冲突。
对于 N
你将使用 ConcurrentBag
而不是 List
因为它是线程安全的。这意味着当两个线程碰巧将物品添加到您的包中时,不会发生奇怪的事情。
如果您删除 Parallel 中的项目,您应该通知所有线程新的更改,这将很难(而且非常难看)实施。
List<string> R = new List<string>();
while (R.Count > 0)
{
var removing = new ConcurrentBag<long>();
var N = new ConcurrentBag<string>();
var first = R[0];
N.Add(first);
R.Remove(first);
Parallel.ForEach(R, (item, state, index) =>
{
if(hamming(first, item))
{
N.Add(item);
R[(int)index] = null; // mark as null and ignore.
// this is not thread safe for versioning of list but doesn't matter.
// for R ConcurrentBag can be used too but it doesn't change results after all.
}
});
// now we are safe to reorganize our collection.
R = R.Where(str => str != null).ToList(); // parallel execution doesn't help. see comments below.
// for very large collection this will finish in few milliseconds.
// get other stuff...
}