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\$ – Dmitry Nogin Jun 2 '16 at 14:29
  • \$\begingroup\$ @DmitryNogin .net platform \$\endgroup\$ – XIAN YU Jun 2 '16 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\$ – Dmitry Nogin Jun 2 '16 at 15:01
  • \$\begingroup\$ @DmitryNogin hi, we use web api controller \$\endgroup\$ – XIAN YU Jun 2 '16 at 15:02
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, privacy policy and cookie policy

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