草庐IT

c# - Parallel.For 在大约 1370 次迭代后卡住,不知道为什么

coder 2024-06-02 原文

我正在对 7500 多个对象运行 Parallel.For 循环。在那个 for 循环中,我对每个对象做了很多事情,特别是调用两个 Web 服务和两个内部方法。 Web 服务只是检查对象、处理并返回一个字符串,然后我将其设置为对象的属性。两个内部方法也是如此。

我没有将任何内容写入磁盘或从磁盘读取。

我还使用标签和进度条更新了 winforms 应用程序中的 UI,让用户知道它的位置。这是代码:

var task = Task.Factory.StartNew(() =>
{
  Parallel.For(0, upperLimit, (i, loopState) =>
  {
     if (cancellationToken.IsCancellationRequested)
        loopState.Stop();
     lblProgressBar.Invoke(
       (Action)
       (() => lblProgressBar.Text = string.Format("Processing record {0} of {1}.", (progressCounter++), upperLimit)));
     progByStep.Invoke(
       (Action)
       (() => progByStep.Value = (progressCounter - 1)));

      CallSvc1(entity[i]);
      Conversion1(entity[i]);
      CallSvc2(entity[i]);
      Conversion2(entity[i]);
  });
}, cancellationToken);

这是在 Win7 32 位机器上进行的。

关于为什么当增量器在 1370 左右(它是 1361、1365 和 1371)时突然卡住的任何想法?

关于如何调试它并查看锁定的内容(如果有的话)有什么想法吗?

编辑:
对以下评论的一些回答:
@BrokenGlass - 不,没有互操作。我会尝试 x86 编译并告诉你。

@chibacity - 因为它在后台任务中,所以它不会卡住 UI。直到它卡住时,进度条和标签以每秒大约 2 的速度滴答作响。当它卡住时,它只是停止移动。我可以验证它停止的数字是否已被处理,但仅此而已。双核 2.2GHz 上的 CPU 使用率在运行期间最低,每次为 3-4%,一旦卡住则为 1-2%。

@Henk Holterman - 大约需要 10-12 分钟才能到达 1360,是的,我可以验证所有这些记录都已处理但未处理其余记录。

@CodeInChaos - 谢谢,我会试试的!如果我取出并行代码,代码确实有效,它只需要永远和一天。我没有尝试限制线程数,但会的。

编辑 2:
关于网络服务的一些细节

Web 服务基本上是在传递一些数据并接收数据(XmlNode)。然后该节点用于 Conversion1 进程,该进程依次设置实体的另一个属性,该属性被发送到 CallSvc2 方法,依此类推。它看起来像这样:

private void CallSvc1(Entity entity)
{
    var svc = new MyWebService();
    var node = svc.CallMethod(entity.SomeProperty);
    entity.FieldToUpdate1.LoadXml(node.InnerXml);
}
private void Conversion1(Entity entity)
{
    // Do some xml inspection/conversion stuff
    if (entity.FieldToUpdate1.SelectSingleNode("SomeNode") == "something") {
        entity.FieldToUpdate2 = SomethingThatWasConverted;
    }
    else {
        // Do some more logic
    }
}
private void CallSvc2(Entity entity)
{
    var svc = new SomeOtherWebService();
    var xmlNode = svc.MethodToCall(entity.FieldToUpdate2.InnerXml);
    entity.AnotherXmlDocument.LoadXml(xmlNode.InnerXml);
}

如您所见,这是非常简单的事情。一些转换方法中发生了很多事情,但没有一个应该是阻塞的。如下所述,有 1024 个线程处于“等待”状态,它们都在进行 Web 服务调用。我在这里阅读http://www.albahari.com/threading/对于 32 位机器上的 .Net 4,MaxThreads 默认为 1023。

我怎样才能释放那些等待中的线程?

最佳答案

一个可能的解释:您已经使进程进入无法创建更多线程的状态,这会阻止工作取得进展,这就是为什么一切都陷入停顿的原因。

坦率地说,无论该假设是否正确,您都需要对此采取完全不同的方法。 Parallel.For 是解决这个问题的错误方法。 (Parallel 最适合 CPU 密集型工作。这里是 IO 密集型工作。)如果您确实需要处理数千个 Web 服务请求,则需要转到使用异步代码,而不是多线程代码。如果您使用异步 API,您将能够在仅使用少量线程的情况下同时启动数千个请求。

这些请求是否真的能够同时执行是另一回事 - 无论您使用当前的“线程启示录”实现还是更高效的异步实现,您都可能会遇到限制。 (.NET 有时会限制它实际发出的请求数。)因此,您可以请求发出任意数量的请求,但您可能会发现几乎所有请求都在等待较早的请求完成。例如。我认为 WebRequest 将与任何单个域的并发连接限制为仅 2 个...启动 1000 多个线程(或 1000 多个异步请求)只会导致加载更多请求等待成为其中之一当前的 2 个请求!

你应该做你自己的节流。您需要决定同时有多少未完成的请求,并确保您一次只启动那么多请求。仅仅要求 Parallel 尽可能快地启动尽可能多的应用程序会使一切陷入困境。

更新添加:

快速修复可能是使用接受 ParallelOptions 对象的 Parallel.For 重载 - 您可以将其 MaxDegreeOfParallelism 属性设置为限制并发请求的数量。这将阻止这个线程繁重的实现实际用完线程。但它仍然是解决问题的低效解决方案。 (据我所知,你确实需要发出数千个并发请求。例如,如果你正在编写网络爬虫,这实际上是一件合理的事情。Parallel 不是不过,该作业的正确类。使用异步操作。如果您使用的 Web 服务代理支持 APM(BeginXxx、EndXxx),您可以将其包装在 Task 对象中 - Task .TaskFactory 提供了一个 FromAsync,它将提供一个表示正在进行的异步操作的任务。

但是如果您打算同时处理数千个请求,则需要仔细考虑您的限制策略。尽可能快地发出请求不太可能是最佳策略。

关于c# - Parallel.For 在大约 1370 次迭代后卡住,不知道为什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4340216/

有关c# - Parallel.For 在大约 1370 次迭代后卡住,不知道为什么的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  3. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  4. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  5. ruby - 为什么 4.1%2 使用 Ruby 返回 0.0999999999999996?但是 4.2%2==0.2 - 2

    为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返

  6. ruby-on-rails - form_for 中不在模型中的自定义字段 - 2

    我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢

  7. ruby - ruby 中的 TOPLEVEL_BINDING 是什么? - 2

    它不等于主线程的binding,这个toplevel作用域是什么?此作用域与主线程中的binding有何不同?>ruby-e'putsTOPLEVEL_BINDING===binding'false 最佳答案 事实是,TOPLEVEL_BINDING始终引用Binding的预定义全局实例,而Kernel#binding创建的新实例>Binding每次封装当前执行上下文。在顶层,它们都包含相同的绑定(bind),但它们不是同一个对象,您无法使用==或===测试它们的绑定(bind)相等性。putsTOPLEVEL_BINDINGput

  8. ruby - Infinity 和 NaN 的类型是什么? - 2

    我可以得到Infinity和NaNn=9.0/0#=>Infinityn.class#=>Floatm=0/0.0#=>NaNm.class#=>Float但是当我想直接访问Infinity或NaN时:Infinity#=>uninitializedconstantInfinity(NameError)NaN#=>uninitializedconstantNaN(NameError)什么是Infinity和NaN?它们是对象、关键字还是其他东西? 最佳答案 您看到打印为Infinity和NaN的只是Float类的两个特殊实例的字符串

  9. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  10. ruby - 为什么 SecureRandom.uuid 创建一个唯一的字符串? - 2

    关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion为什么SecureRandom.uuid创建一个唯一的字符串?SecureRandom.uuid#=>"35cb4e30-54e1-49f9-b5ce-4134799eb2c0"SecureRandom.uuid方法创建的字符串从不重复?

随机推荐