I use Task Parallel Library(TPL) and C# 4.5 to implement this business logic in a Windows Service Application:
- Get JSON result (a list) from remote RESTful API
- For each item, retrieve JSON result of details from another remote RESTful API
- For each item's attached business objects(1000+), use Parallel.ForEach saving to database
Currently the problem is: It may take long time saving each item to database (Sync DAL), so Parallel.ForEach 1000 items takes forever and the Windows Service application appears slower and slower. Does anyone have good ideas or better approach to gain better performance?
Code snippet:
/* 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 */
});
}
});
Update: (the code for DBLongProcess() and the lock (I added lock because concurrent threads may attempt to modify same object to 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
}
}
}
}
DBLongProcessprovide thread safety? If done wrong that easily could be the source of your slowness. Can you include the code for that too? - Scott Chamberlain