使用 async/await 时,我的控制台应用程序过早关闭? [英] My console app shutdown prematurely when using async / await?

查看:54
本文介绍了使用 async/await 时,我的控制台应用程序过早关闭?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个控制台应用程序,它所做的只是遍历所有客户并向特定客户发送电子邮件,然后关闭.我注意到 MailKit 中的一些函数提供异步功能,所以我尝试使用它们而不是非 aysnc,当我这样做时,它执行了第一条语句 (emailClient.ConnectAsync),然后我注意到我的控制台应用程序正在关闭.它没有崩溃.执行返回到 Main() 并在我调用 SendReports() 函数后继续执行.

I have a console app that all it does is loop through all the customers and send emails to specific ones and then shutdown. I noticed that some of the functions in MailKit’s offer asynchronous so I tried using them instead of non-aysnc and when I did that, it executed the first statement (emailClient.ConnectAsync) on and then I noticed that my console app was shutting down. It didn’t crash. The execution returned to Main() and continued executing after my call to my SendReports() function.

private static void Main(string[] args)
{
  ...
  var reportServices = new ReportsServices();

  reportServices.SendReportsToCustomers();

  Log.CloseAndFlush();  // It executes the first await call then returns here.
}

internal class ReportsServices
{
  public async void SendReportsToCustomers()
  {
    try
    {
      foreach (var customer in _dbContext.Customer)
      {
          ...
          await SendReport(customer.Id, repTypeId, freqName);
      }
    }
    catch (Exception e)
    {
      Console.WriteLine(e);
      throw;
    }
  }

  private async Task SendReport(int customerId, int repTypeId, string freqName)
  {
    try
    {
      ...
        var es = new EmailSender();
        await es.SendAsync();
      }
    }
    catch (Exception e)
    {
      Console.WriteLine(e);
      throw;
    }

  }
}

public class EmailSender
{
  public async Task SendAsync()
  {
    try
    {
      var message = new MimeMessage();

      ...

      using (var emailClient = new SmtpClient())
      {
        await emailClient.ConnectAsync("smtp.gmail.net", 587);  
        await emailClient.AuthenticateAsync("username", "password"); // If I put a debug break here, it doesn't hit.
        await emailClient.SendAsync(message);
        await emailClient.DisconnectAsync(true);

       // If I use the following calls instead, my console app will not shutdown until all the customers are sent emails.

await emailClient.Connect("smtp.gmail.net", 587);  
await emailClient.Authenticate("username", "password"); // If I put a debug break here, it doesn't hit.
await emailClient.Send(message);
await emailClient.Disconnect(true);

      }
    }
    catch (Exception e)
    {
      Console.WriteLine(e);
      throw;
    }

  }
}

我不明白的是为什么我的循环不会继续遍历所有客户?- 还有更多的工作要做.不知道为什么会跳回到 Main 函数.

What I don't get is why wouldn't my loop continue looping through all the customers? - there is more work for it. Not sure why it would skip back to the Main function.

我所希望的是循环会继续通过所有客户并发送电子邮件;无需等待发送电子邮件即可继续处理下一封邮件.

What I was hoping for is that loop would continue through all the customers and send emails; not having to wait for the email to be sent before continuing on the next one.

感谢您的帮助!

推荐答案

首先,您应该 避免 异步无效方法,ReportsServices.SendReportsToCustomers() 应返回Task.您的代码调用该方法但不等待它完成,该方法是异步的,因此它在第一个等待时返回.您应该在 Main() 中等待它完成.有两种方法可以做到:

First, you should AVOID async void methods, ReportsServices.SendReportsToCustomers() should return Task. Your code invokes the method but does not wait for it to finish, the method is asynchronous so it returns on the first await.you should wait for it to finish in Main(). There are 2 ways to do it:

如果您使用的是 C# 7,则允许使用 async Main:

If you'are using C# 7, async Main is allowed:

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.
}

如果没有,则必须同步等待操作完成:

If not, you'll have to synchronously wait for the operation to finish:

private static void  Main(string[] args)
{
  ...
  var reportServices = new ReportsServices();

  reportServices.SendReportsToCustomers().Wait();;

  Log.CloseAndFlush();  // It executes the first await call then returns here.
}

这是一个文章 进一步解释.

Here is an article with further explanation.

这篇关于使用 async/await 时,我的控制台应用程序过早关闭?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆