我有一个场景,一旦获得学生列表,我必须并行/独立地运行学生列表。但是,当我运行以下有类似代码的程序时,程序结束而没有正确完成。
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
}
}
当我看到UpdateStudentAsync
导致问题时,如果使用F10
,则此方法不会返回任何内容并且控制台应用停止。即使我把每一个电话都放在try-catch
我也找不到任何东西。如果我进入每个调试点,我得到预期的结果。
无法理解问题所在。
答案 0 :(得分:1)
您的ProcessSingleStudent不会等待foreach中每个调用的结果。所以它在迭代后终止
答案 1 :(得分:0)
请记住,async-await具有传染性,或者 ProcessSingleStudent 方法本身不是异步的,它是同步的。你需要的是像
private async Task ProcessSingleStudent(IEnumerable<StudentModel> students)
{
await students.ForEach(async student =>
{
await ValidateSingleStudentAsync(student).ConfigureAwait(false);
}).ConfigureAwait(false)
}
但如果没有一个名为AsyncEnumerator的库的帮助,这是不可能的(它不会编译)。
代码变为
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)
}