1

I have a scenario where I have to run list of students in parallel/independently once I get list of students. However when I run those with following kinda code, program ends without completing properly.

public async Task ProcessStudents()
{
    var students = await GetStudentsAsync().ConfigureAwait(false);
    ProcessSingleStudent(students);
}

private static ProcessSingleStudent(IEnumerable<StudentModel> students)
{
    students.ForEach(async student =>
    {
         await ValidateSingleStudentAsync(student).ConfigureAwait(false);
    }
}

private async Task ValidateSingleStudentAsync(StudentModel student)
{
     //Do some validations here
     if(validate)
     {
       var updated =  await UpdateStudentAsync(student).configureAwait(false); //<== This cause issue
     }
}

As I see UpdateStudentAsync causing issue, that if go with F10 this method doesn't return anything and console app stops. Even I put every call in try-catch I couldn't find anything. If I step in each debug point, I get expected result.

Unable to understand where is the issue.

Avi Kenjale
  • 2,414
  • 6
  • 29
  • 46

2 Answers2

1

Your ProcessSingleStudent doesn't await the results of each call in the foreach. So it terminates after iterating

You want something like this: https://stackoverflow.com/a/15136833/8302901

Dan
  • 858
  • 7
  • 18
  • You were right, instead of running asynchronous method in foreach, I am adding returning task into a task list and then passing that task list to `Task.WhenAll()` – Avi Kenjale Sep 15 '17 at 19:49
0

Remember that async-await is contagious or ProcessSingleStudent method is not itself async, it's synchronous. What you need is something like

private async Task ProcessSingleStudent(IEnumerable<StudentModel> students)
{
    await students.ForEach(async student =>
    {
         await ValidateSingleStudentAsync(student).ConfigureAwait(false);
    }).ConfigureAwait(false)
}

But this is not possible (it doesn't compile) without a little bit of help of a library named AsyncEnumerator.

The code becomes

private async Task ProcessSingleStudent(IEnumerable<StudentModel> students)
    {
        await students.ParallelForEachAsync(async student =>
        {
             await ValidateSingleStudentAsync(student).ConfigureAwait(false);
        },
         maxDegreeOfParalellism: 30,
         cancellationToken: null,
         breakLoopOnException: true
        ).ConfigureAwait(false)
    }
Adrian Iftode
  • 15,465
  • 4
  • 48
  • 73