【发布时间】:2014-01-13 04:34:30
【问题描述】:
我使用任务并行库 (TPL) 和 C# 4.5 在 Windows 服务应用程序中实现此业务逻辑:
- 从远程 RESTful API 获取 JSON 结果(列表)
- 对于每个项目,从另一个远程检索详细信息的 JSON 结果 RESTful API
- 对于每个项目的附加业务对象(1000+),使用 Parallel.ForEach 保存到数据库
目前的问题是:将每个项目保存到数据库(同步 DAL)可能需要很长时间,因此 Parallel.ForEach 1000 个项目需要很长时间,并且 Windows 服务应用程序看起来越来越慢。有没有人有好的想法或更好的方法来获得更好的性能?
代码sn-p:
/* Download a list from RESTful API URL.... */
var task = Task.Factory.StartNew(() => { return DownloadListFromRestAPI(); }, TaskCreationOptions.LongRunning);
task.ContinueWith(i => {
foreach (var r in i.Result)
{
/* For each item, download the item details from RESTful API URL.... */
var taskSecond = Task.Factory.StartNew(() => { return DownloadItemDetailFromRestAPI(r.id); }, TaskCreationOptions.LongRunning);
taskSecond.ContinueWith(m => {
/* For each item detail, get the related business objects, and start Database operation on each object.... */
List<Item> relatedItems_1000 = s.GetRelatedObjectsIds(m.Result.id);
/* parallel.ForEach - 1000 or more items */
Parallel.ForEach<Item>(relatedItems_1000, new ParallelOptions { MaxDegreeOfParallelism = 8 }, d => DBLongProcess(d)); /* The DB operation takes long time */
});
}
});
更新:(DBLongProcess() 的代码和锁(我添加了锁,因为并发线程可能会尝试将同一对象修改为 DB))
private void DBLongProcess(Item item)
{
dbDAL.InsertObjectDB(item));
}
public class DBDAL
{
private readonly object _lock = new object();
public void InsertObjectDB(Item item)
{
lock (_lock)
{
if(!item.hasDetail1()){
//insert item.detail1...
}
if(!item.hasDetail2()){
//insert item.detail2
}
}
}
}
【问题讨论】:
-
DBLongProcess如何提供线程安全?如果做错了,那很容易成为你迟钝的根源。你能把代码也包括进去吗? -
@ScottChamberlain,请查看我的更新。谢谢你!
-
不清楚实际问题是什么。 UI 变慢是因为后台占用了太多资源?
-
@NahumLitvin,问题是性能很差。我没有 UI 和 backgroundworker,它是一个服务应用程序。我的问题是“parallel.foreach 1000 个项目”这一行似乎永远需要......有没有更好的方法来获得更好的性能?
-
你的服务器线程不安全吗?为什么是锁?
标签: c# performance c#-4.0 parallel-processing task-parallel-library