我发布的内容部分是关于任务并行库如何工作以及传播知识。此外,还要调查我的“取消”更新是否是导致用户突然退出的新问题的原因。
我正在开发的项目包含以下组件:
注意:我使用的是.NET 4.0。因此,对任务并行库的较新更新不可用。
我被分配修复的问题是登录功能非常慢并且CPU密集。后来这被认为是第三方服务中的问题。但是我试图尽可能地优化登录行为。
登录请求和响应不包含特别多的数据。但是,为了收集响应数据,会对第三方服务进行几次API调用。
Web 在服务上调用WCF方法以收集“会话数据”。 这种方法有时需要很长时间才会超时(我认为超时设置为1分钟)。
“GetSessionData”方法的伪表示:
var agreements = getAgreements(request);
foreach (var agreement in agreements)
{
getAgreementDetails(agreement);
var customers = getCustomersWithAgreement(agreement);
foreach (var customer in customers)
{
getCustomerInfo(customer);
getCustomerAddress(customer);
getCustomerBranches(customer);
}
}
var person = getPerson(request);
var accounts = getAccount(person.Id);
foreach (var account in accounts)
{
var accountDetail = getAccountDetail(account.Id);
foreach (var vehicle in accountDetail.Vehicles)
{
getCurrentMilageReport(vehicle.Id);
}
}
return sessionData;
请参阅gist了解代码段。
用户拥有的agreements
和accounts
越多,此方法就会越来越重。
我想我可以用foreach
替换Parallel.ForEach()
个循环。这大大提高了大用户的方法速度。
请参阅gist了解代码段。
我们遇到的另一个问题是,当Web服务器服务器的CPU使用率最大化时,所有方法调用都会变慢,并且可能导致用户超时。并且对超时的流行响应是再次尝试,因此用户触发另一次由于CPU使用率高而“排队”(?)的登录尝试。这一切都在第一个请求尚未返回时。
我们发现如果网站超时,请求仍然存在。所以我们决定在 Service 方面实现类似的超时。
请参阅gist了解代码段。
我们的想法是使用CancellationToken调用GetSessionData(..),在与 Web 超时大约相同的时间后触发取消。如果没有人在那里展示或使用结果,那么就不会做任何工作。
我还实现了对第三方服务的方法调用的取消。
为所有循环和服务调用共享相同的CancellationToken是否正确?当抛出取消异常所有线程被“中止”时会出现问题吗?
请参阅gist了解代码段。
答案 0 :(得分:3)
为所有循环和服务调用共享相同的CancellationToken是否正确?当所有线程都通过抛出取消异常而“中止”时会出现问题吗?
是的,这是正确的。是的,可能存在同时抛出大量异常的问题,但仅限于特定情况和大量并行工作。
一些提示:
我在工作结束时感到很累,并提出了一件坏事。主要是,您不需要用于IO绑定工作的线程,例如,等待来自第三服务的数据库的响应。仅将线程用于CPU计算。
此外,我再次审核了您的代码,发现了几个瓶颈: