PKo*_*ant 1 c# multithreading mailkit
我有一个控制台应用程序,它所做的就是循环所有客户并向特定客户发送电子邮件,然后关闭。我注意到 MailKit\xe2\x80\x99s 中的一些函数提供异步功能,因此我尝试使用它们而不是非 aysnc,当我这样做时,它执行了第一个语句 (emailClient.ConnectAsync),然后我注意到我的控制台应用程序正在关闭。它没有\xe2\x80\x99t崩溃。在调用 SendReports() 函数后,执行返回到 Main() 并继续执行。
\n\nprivate static void Main(string[] args)\n{\n ...\n var reportServices = new ReportsServices();\n\n reportServices.SendReportsToCustomers();\n\n Log.CloseAndFlush(); // It executes the first await call then returns here.\n}\n\ninternal class ReportsServices\n{\n public async void SendReportsToCustomers()\n {\n try\n {\n foreach (var customer in _dbContext.Customer)\n {\n ...\n await SendReport(customer.Id, repTypeId, freqName);\n }\n }\n catch (Exception e)\n {\n Console.WriteLine(e);\n throw;\n }\n }\n\n private async Task SendReport(int customerId, int repTypeId, string freqName)\n {\n try\n {\n ...\n var es = new EmailSender();\n await es.SendAsync();\n }\n }\n catch (Exception e)\n {\n Console.WriteLine(e);\n throw;\n }\n\n }\n}\n\npublic class EmailSender\n{\n public async Task SendAsync()\n {\n try\n {\n var message = new MimeMessage();\n\n ...\n\n using (var emailClient = new SmtpClient())\n {\n await emailClient.ConnectAsync("smtp.gmail.net", 587); \n await emailClient.AuthenticateAsync("username", "password"); // If I put a debug break here, it doesn\'t hit.\n await emailClient.SendAsync(message);\n await emailClient.DisconnectAsync(true);\n\n // If I use the following calls instead, my console app will not shutdown until all the customers are sent emails.\n\nawait emailClient.Connect("smtp.gmail.net", 587); \nawait emailClient.Authenticate("username", "password"); // If I put a debug break here, it doesn\'t hit.\nawait emailClient.Send(message);\nawait emailClient.Disconnect(true);\n\n }\n }\n catch (Exception e)\n {\n Console.WriteLine(e);\n throw;\n }\n\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n我不明白的是为什么我的循环不能继续循环所有客户?- 还有更多的工作要做。不知道为什么它会跳回主函数。
\n\n我所希望的是,循环将继续通过所有客户并发送电子邮件;无需等待电子邮件发送即可继续下一封。
\n\n我感谢您的帮助!
\n首先,您应该避免async void 方法,ReportsServices.SendReportsToCustomers()应该 return Task。您的代码调用该方法,但不等待它完成,该方法是异步的,因此它在第一个等待时返回。您应该在 Main() 中等待它完成。有两种方法可以做到这一点:
如果您使用 C# 7,则允许使用 async Main:
private static async Task Main(string[] args)
{
...
var reportServices = new ReportsServices();
await reportServices.SendReportsToCustomers();
Log.CloseAndFlush(); // It executes the first await call then returns here.
}
Run Code Online (Sandbox Code Playgroud)
如果没有,您将必须同步等待操作完成:
private static void Main(string[] args)
{
...
var reportServices = new ReportsServices();
reportServices.SendReportsToCustomers().Wait();;
Log.CloseAndFlush(); // It executes the first await call then returns here.
}
Run Code Online (Sandbox Code Playgroud)
这是一篇有进一步解释的文章。