1
\$\begingroup\$

In web api controller: I am a newer in parallel and Async&Task programming. Need someone help me code review.

public async Task<IHttpActionResult> DoWork()
{
    List<string> listTask = await Helper.GetBlockBlock();
    userIds = listTask;
    this.ParallelTaskWork();//step 1,must be finished,but I an not sure when..
    await this.Service.GetAllClientInterestInfoList();//executing after step 1 
    return this.Ok();
}
public async void ParallelTaskWork()
{
    Task[] taskList = this.TaskMaker(totalNum);
}
public Task[] TaskMaker(int threadNum)
{
    Task[] taskList = new Task[threadNum];
    Parallel.For(0, taskList.Length, i => taskList[i] = new Task(this.ProcessDealTask));
    Parallel.ForEach(taskList, t => t.Start());
    return taskList;
}
private void ProcessDealTask()
{
    for (int i = 0; i < totalNum; i++)
    {
        List<string> users = this.GetPartitionOfList(userIds, i, totalNum);
        Task task = this.ParallelDealUserList(users);
        task.Wait();
    }
}
private List<T> GetPartitionOfList<T>(List<T> userList, int index, int total)
{
    int section = (userList.Count / total) + 1;
    int end = (index + 1) * section > userList.Count ? userList.Count - index * section : section;
    if (end < 0) end = 0;
        int start = index * section < userList.Count ? index * section : userList.Count - 1;
    if (start < 0) start = 0;
        return userList.GetRange(start, end);
}
private async Task ParallelDealUserList(IEnumerable<string> list)
{
    await Task.Run(() => Parallel.ForEach(list, async (id, loopState) =>
    {
        try
        {
            await GrainClient.GrainFactory.GetGrain<IUser>(id.ToGuid()).DoProcessInterestAsync(true);
        }
        catch (Exception e)
        {
        }
    }));
}

Any performance problem? The method ParallelDealUserList I refer to https://stackoverflow.com/questions/19102966/parallel-foreach-vs-task-run-and-task-whenall somebody said

there is a disadvantage to use Task.Run in a loop- With Parallel.ForEach, there is a Partitioner which gets created to avoid making more tasks than necessary

and The method TaskMaker https://stackoverflow.com/questions/22988630/parallel-for-w-action-that-creates-different-tasks-c-sharp

\$\endgroup\$
4
  • \$\begingroup\$ What kind of process you are running? ASP.NET? \$\endgroup\$ Jun 2, 2016 at 14:29
  • \$\begingroup\$ @DmitryNogin .net platform \$\endgroup\$
    – YUu
    Jun 2, 2016 at 14:57
  • \$\begingroup\$ OK, but is it ASP.NET or ASP.NET MVC, or WPF, or WinForms, or Console (Service)? What kind of Task Scheduler are you using? \$\endgroup\$ Jun 2, 2016 at 15:01
  • \$\begingroup\$ @DmitryNogin hi, we use web api controller \$\endgroup\$
    – YUu
    Jun 2, 2016 at 15:02

2 Answers 2

4
\$\begingroup\$

First thing is that you should limit the degree of parallelism, to ex: 4 threads

Parallel.ForEach(
    listOfWebpages,
    new ParallelOptions { MaxDegreeOfParallelism = 4 },
    webpage => { Download(webpage); }
);

Without this, you are going to DDoS your service or resource you are using.


You seem to be using Project Orleans and AFAIK a grain should be a single threaded container. You should be able to do just:

private void ParallelDealUserList(IEnumerable<string> list)
{
    foreach(var item in list)
        GrainClient
            .GrainFactory
            .GetGrain<IUser>(item.id.ToGuid())
            .DoProcessInterestAsync(true);
}

I am not all that familiar with Project Orleans. Most likely this can be used, but I would use microservices (aka SOA2) instead.

\$\endgroup\$
4
\$\begingroup\$

It is really dangerous to fork background threads in ASP.NET. Task Scheduler immediately gets crazy, which degrades performance significantly.

There is a way though: HostingEnvironment.QueueBackgroundWorkItem.

QBWI schedules a task which can run in the background, independent of any request. This differs from a normal ThreadPool work item in that ASP.NET automatically keeps track of how many work items registered through this API are currently running, and the ASP.NET runtime will try to delay AppDomain shutdown until these work items have finished executing.

Please have a look at How to run Background Tasks in ASP.NET

\$\endgroup\$
3

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.