提问者:小点点

在foreach循环(c#)内调用异步函数


我在一个循环中调用了一个异步函数来发送电子邮件,但是有一段时间控件没有返回,也没有发送电子邮件,但是主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方法中有很多异步方法,所以我认为有些线程彼此重叠。任何线索。


共1个答案

匿名用户

如果不知道内部发生了什么,我们无法确定发生了什么。但是,这一行:

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()被阻止,那么在新的任务中包装(如上面的最后一个示例)可能会有所帮助。

相关问题