1
public List<Order.RootObject> DoStuff ()
    {
        List<Order.RootObject> cOrders = new List<Order.RootObject>();

        var client = new RestClient(url);
        var request = new RestRequest("orders", Method.GET);

        request.AddParameter("pgsize", "2000");
        request.AddParameter("pgnum", "1");

        var response = client.Execute<Order.RootObject>(request);
        int iLoop = response.Data.TotalResults / 2000 + 1;
        Parallel.For(1, iLoop,
             index => {
                 request.Parameters[“pgnum”].Value = index;
                 response = response = client.Execute<Order.RootObject>(request);
                 cOrders.Add(response.Data);
             });
        return cOrders;
    }

cOrders 不会以 API 返回的所有响应结束。如果我将它更改为一个简单的 For 循环,一切都很好,但它需要很长时间,因为对于某些调用,有许多循环返回 API 来获取我需要的所有数据。

4

2 回答 2

1

您正在循环内重用请求对象。那是行不通的,因为多个线程将访问和修改这个单个实例。您必须同步/锁定对请求实例的访问(然后您有一个没有并行化的普通 for 循环)或为循环内的每个请求创建一个自己的请求对象......

于 2017-09-29T15:04:13.427 回答
1

列表不是线程安全的。框架中的大多数类型都不是。在多线程上下文中使用一个时,请确保检查文档

此类型的公共静态(在 Visual Basic 中为 Shared)成员是线程安全的。不保证任何实例成员都是线程安全的。对 List 执行多个读取操作是安全的,但如果在读取集合时对其进行了修改,则可能会出现问题。为确保线程安全,请在读取或写入操作期间锁定集合。要使一个集合能够被多个线程访问以进行读写,您必须实现自己的同步。对于具有内置同步的集合,请参阅 System.Collections.Concurrent 命名空间中的类。对于固有的线程安全替代方案,请参阅 ImmutableList 类。

我真的很喜欢不可变集合,并且在大多数情况下更喜欢它们而不是并发集合。不幸的是,对于新用户来说,它们有点难以使用和理解。任何突变都会产生一个新的集合,然后您必须使用它来替换旧版本。这本身不是类型安全的,但它们附带了一个工具,可以为您处理所有这些。

var foo = ImmutableList<string>.Empty;
ImmutableInterlocked.Update(ref foo, list => list.Add("woot"));

list.Add("woot")返回一个基于 的新列表foo,并且ImmutableInterlocked.Update将尝试更新foo,直到确定集合引用已正确更新。你用重做你的工作 ( list.Add("woot")) 来代替锁定。

于 2017-09-29T15:19:37.547 回答