我正在对 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/
类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
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
我主要使用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
为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返
我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢
它不等于主线程的binding,这个toplevel作用域是什么?此作用域与主线程中的binding有何不同?>ruby-e'putsTOPLEVEL_BINDING===binding'false 最佳答案 事实是,TOPLEVEL_BINDING始终引用Binding的预定义全局实例,而Kernel#binding创建的新实例>Binding每次封装当前执行上下文。在顶层,它们都包含相同的绑定(bind),但它们不是同一个对象,您无法使用==或===测试它们的绑定(bind)相等性。putsTOPLEVEL_BINDINGput
我可以得到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类的两个特殊实例的字符串
如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象
关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion为什么SecureRandom.uuid创建一个唯一的字符串?SecureRandom.uuid#=>"35cb4e30-54e1-49f9-b5ce-4134799eb2c0"SecureRandom.uuid方法创建的字符串从不重复?