我在一个循环中调用了一个异步函数来发送电子邮件,但是有一段时间控件没有返回,也没有发送电子邮件,但是主UI线程完成了。
var sendEmailtasks = new List<Task>();
foreach (var email in emailList)
{
var emailResTask = Task.Run(async() => await
emailingService.SendEmail(email));
sendEmailtasks.Add(emailResTask);
}
await Task.WhenAll(sendEmailtasks);
当我把等待任务。WhenAll(发送电子邮件任务);循环内的线工作正常,但当我把这条线放在循环外时,它不工作,但实际上它应该在循环外。我在sendEmail方法中有很多异步方法,所以我认为有些线程彼此重叠。任何线索。
如果不知道内部发生了什么,我们无法确定发生了什么。但是,这一行:
var emailResTask = Task.Run(async() => await emailingService.SendEmail(email));
看起来很可疑。如果SendEmail()
函数返回任务
,则可以简化代码:
Console.WriteLine("Creating tasks");
foreach (var email in emailList)
{
var emailResTask = emailingService.SendEmail(email);
sendEmailtasks.Add(emailResTask);
}
Console.WriteLine("Finished creating tasks");
await Task.WhenAll(sendEmailtasks);
但是,如果您的SendEmail()
函数不是异步的,它可能仍然会阻塞,并且您不会看到您的任务并行运行;例如,此方法:
public Task SendEmail(string email)
{
Console.WriteLine($"Sending email to {email}");
Task.Delay(3000).Wait();
Console.WriteLine($"Done ({email}).");
return Task.CompletedTask;
}
将首先执行,然后返回:
Creating tasks
Sending email to one
Done (one).
Sending email to two
Done (two).
Finished creating tasks
但是,此函数不会阻塞(通过使用异步延迟方法):
public async Task SendEmail(string email)
{
Console.WriteLine($"Sending email to {email}");
await Task.Delay(3000);
Console.WriteLine($"Done ({email}).");
return Task.CompletedTask;
}
这一块也不会:
public Task SendEmail(string email)
{
return Task.Factory.StartNew(() =>
{
Console.WriteLine($"Sending email to {email}");
Thread.Sleep(3000);
Console.WriteLine($"Done ({email}).");
});
}
以上两个示例都在我的计算机上输出以下内容:
Creating tasks
Sending email to one
Sending email to two
Finished creating tasks
Done (one).
Done (two).
如果您的sendmail()
被阻止,那么在新的任务
中包装(如上面的最后一个示例)可能会有所帮助。