希望你们中的一些人可以就这一点给出一些指示。
我生成代码,我必须调用远程资源,如webservices或数据库。
考虑这段代码
class Parent{
IEnumerable<Child> Children;
int SumChildren() {
// note the AsParallel
return Children.AsParallel().Sum(c => c.RemoteCall());
}
}
class Child {
public int RemoteCall() {
// call some webservice. I'd like to pool these calls
// without having to rewrite the rest of this code
}
}
对于50个孩子,它将拨打50个电话,占用开销50次。在我的现实生活中,这可能很容易就是一百万个电话,让整个事情陷入困境。
我想做的是以某种方式批量调用这些调用,这对调用线程/任务是透明的。因此,它不是直接调用服务,而是调用一些批处理这些调用的中央队列(“火车站”)。
这样,当它这样做时,调用任务就会阻塞。然后队列等待X调用累积,然后使用请求列表对远程服务进行1次调用。
当结果出现时,此队列将返回值返回到正确的任务并取消阻止。对于调用线程,所有这些都保持隐藏,它看起来只是另一个函数调用。
可以这样做吗? TPL中是否有基元可以让我这样做?
它有点像CCR,同时还有很多东西在等待其他东西完成。
我当然可以重写此代码以在Parent类上创建请求列表,然后调用该服务。问题在于,我的真正问题是生成所有这些代码。所以我必须'查看'Child.RemoteCall的实现,使这一切变得比现在复杂得多。此外,孩子可能是远程对象的代理等。如果可行的话会非常困难,我宁愿孤立这种复杂性。
希望这对某人有意义,如果不让我知道我会详细说明。
答案 0 :(得分:3)
你正在大规模并行编程的表面。你需要在concurrency oriented way中思考。您正在启动51个作业,而不是您需要批量处理的50个作业。额外的工作是管理50个工作的工作。就你需要的基元而言。
JOBHANDLE X= GetJobId();
//single job
AddJob(JOBHANLDE X,ChildJob y);
//container of jobs
AddJobs(JOBHANDLE x, ChildJobs Y);
BeginAsyncExecute(JOBHANDLE X);
WaitTillResult(JOBHANDLE X);
您需要一个后台引擎来定义阻塞原语(超出操作系统内核提供的原语)并管理工作线程和要执行的作业,从外观来看它由PLINQ技术处理。 PLINQ也使用绿色线程,这很好。
您提到过您将拥有数据库和Web服务器的混合体。因此,您的作业流程/功能必须在执行批处理之前将子项映射到正确的资源。因此,可以将50个孩子减少到可批处理的RPC调用。
因此,您构建了Job批处理,然后阻止它。
变得更具体是很难的。但鉴于到目前为止的讨论,请告诉我你遇到了什么麻烦。
答案 1 :(得分:1)
这样,当它这样做时,调用任务就会阻塞。然后队列等待X调用累积
如果队列接收到x个调用(x
如果您的应用程序通常运行很多任务,那么您可能只会间歇性地看到此问题 - 您的负载异常低或干净关闭。
您可以通过添加超时来解决此问题,以便如果在时间限制内未添加任何请求,并且/或第一个请求等待的时间超过时间限制,则队列将始终发送已批处理的请求。 / p>
我当然可以重写此代码以在Parent类上创建请求列表,然后调用该服务。
也许你采用这种方法走在正确的轨道上。你能找到一种用手工编码的实现,委托,继承,lambda方法或增强你的生成器来替换生成的方法实现的方法吗?
...我的真实问题是生成所有这些代码。
我不太清楚的一点是代码的哪些部分是生成的(难以修改)以及代码的哪些部分可以修改以解决这个问题?
如果它不属于上述情况,则必须能够修改某些内容才能解决问题。父和子实例是否由AbstractFactory构建?如果是,则可以向Child实例插入代理,该代理可用于修改其行为的非功能方面。
答案 2 :(得分:0)
(使用空格的答案框)
感谢您的想法。
“这会......”: 我处理从存储库生成的代码。在处理这个问题的手写代码示例时,开发人员可以发现并改进它。通过生成代码,很难从一组问题示例中提炼出一般情况。这可能变得非常复杂,所以我的策略是狡猾和征服。如果我必须看看出门的孩子的功能。
“我发现了这个链接......”: 我看过Futures,但这更像是一个可以在空闲线程时进行并行化的分叉机制。
TPL似乎是将工作分成小部分。我想要做的是取一些这些位并将它们组合在一起以不同的组合,然后将它们再次拆分以进行并行执行。 (我想,还是在精神上咀嚼这个......)
“再想一想”: 再一次,摒弃和征服战略让我走得更远。因此,我将更大的问题分解为小位,解决它们然后将这些位重新组合在一起。我喜欢想到一个蚁群,每个蚂蚁遵循简单的规则(或看板,这是一个类似的原则),而不是一些中央管理事物(查询优化器)快速陷入困境,因为它变得非常复杂非常快。
当父母可以以可并行化的方式调用50个子节点时,这些单独的任务可以被批处理,因为他们指向的是相同的远程资源。
这里的主要障碍是我如何让调用任务(或线程或其他任何一个执行单元)阻塞,让另一个拾取一批它们的工作,做到这一点,将答案放入集合中所有的任务都把他们的工作和他们再次唤醒了。 (然后以有效的方式......)。
我想我记得George Chrysanthakopoulos(那个创建CCR的人)说的是收益率回报陈述是他过去常常做的事情。我会试着再次在Channel9上找到那次采访。
关心GJ