首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ThreadSafe Parallel.For

ThreadSafe Parallel.For
EN

Stack Overflow用户
提问于 2017-09-29 22:58:37
回答 2查看 228关注 0票数 1
代码语言:javascript
复制
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最终不会返回所有的响应。如果我将它改为一个简单的For循环,一切都很好,但它需要很长时间,因为对于某些调用,需要返回到API的许多循环才能获得所需的所有数据。

EN

回答 2

Stack Overflow用户

发布于 2017-09-29 23:04:13

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

票数 1
EN

Stack Overflow用户

发布于 2017-09-29 23:19:38

List不是线程安全的。框架中的大多数类型都不是。当在多线程上下文中使用一个类型时,请确保使用check the docs

此类型的

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

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

代码语言:javascript
复制
var foo = ImmutableList<string>.Empty;
ImmutableInterlocked.Update(ref foo, list => list.Add("woot"));

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46491597

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档