0

我在使用 Parallel.For 方法时遇到问题。我正在打一个 GET 电话以取回一份清单。然后我想把那个列表添加到主列表中。我已经尝试过 addRange ,它不是线程安全的,并且会在列表中返回错误的数据。我也尝试使用 ConcurrentBag 也没有得到正确的数据。当我说没有得到正确的数据时,我的意思是列表中的一些数据要么重复,要么被覆盖。

这是我的代码(更新):

var thisLock = new Object();
var list = new List<Person>();
Parallel.For(1, 10, x =>
{
    request.Page = x;
    response = Get(request); // call to client
    lock(thisLock)
    {
        list.AddRange(response);
    }
}

除了 addRange 或 ConcurrentBag 之外的任何其他想法

4

2 回答 2

4

我在这里做了一些假设,但您的问题似乎是您的request/response变量不在Parallel.For调用范围内。

问题是您进行了(可能)同步Get调用来更新response变量,但假设您有 X 个线程都在使用相同的响应,如果在任何给定点更新,即当另一个线程将它添加到列表中时,那就是会很好地导致重复数据。

也是如此request,你有一个明显的竞争条件,这意味着当一个线程更改request.Page并且另一个线程即将拉数据时,你实际上是在跨多个线程拉同一个页面。

解决方案很简单,在本地创建你的request/对象response

var list = new ConcurrentBag<T>();
Parallel.For(1, 10, x =>
{
    var request = // create new request;
    request.Page = x;
    var response = Get(request); // call to client
    foreach (var item in response) {
        list.Add(item); // add it main list
    }
}
于 2014-06-11T14:35:55.883 回答
0

这是 PLINQ 的一个很好的候选。然后,您可以SelectMany用于展平序列。

var list = ParallelEnumerable.Range(1, 10).SelectMany(x =>
{
    var request = // create new request;
    request.Page = x;
    response = Get(request); // call to client
    return response;
}).ToList();
于 2014-06-11T20:13:20.000 回答