【问题标题】:How call async method from non async web API如何从非异步 Web API 调用异步方法
【发布时间】:2020-03-10 00:19:21
【问题描述】:

我有 web api,它是非异步的。

从那个 web api,我正在调用方法

SmtpClient.SendMailAsync(email);

此电子邮件已发送给相应的人,但下一个 Web api 请求获取失败。

public class TestController : ApiController
{
    public TestController(TestService testService)
    {
       _testService = testService;
    }

    public IHttpActionResult Post(data)
     {
         _testService.SendEmail(data);
     }
}

public class TestService 
{
    public async Task SendEmail(MailMessage email)
     {
        SmtpClient client = new SmtpClient();
        client.SendMailAsync(email)
     }
}

【问题讨论】:

  • 通常还有一个非Async Method。在这种情况下,SendMail 而不是 SendMailAsync。
  • 用_testService.SendEmail(data).GetAwaiter().GetResult()替换_testService.SendEmail(data);
  • @ravikumar:我不想等到电子邮件发送完毕,我想要一些行为,比如一发不可收拾。
  • @HemantMalpote:注意,SmtpClient 必须被处理掉。将其包装成using。
  • @Dennis:同意

标签: c# asp.net-web-api async-await


【解决方案1】:

从引入异步/等待模式之前的日子开始,框架类中仍然存在许多非异步函数。

SmtpClient 客户端是足以满足此要求的类之一。 SendFunction 是您正在寻找的机器人:

https://docs.microsoft.com/en-us/dotnet/api/system.net.mail.smtpclient.send

虽然命名有点偏离并且它们返回 void,但这些似乎是预异步函数。在这两种情况下都应该通过异常来传达失败。

【讨论】:

    【解决方案2】:

    鉴于您希望 SendEmail 表现得像火一样忘记,我建议使用

    Task.Run(() => _testService.SendEmail(data));
    

    这会将工作单元分配给线程池,并将您的请求从等待该任务的职责中解放出来。一般来说,这被建议用于火灾和忘记。

    根据经验,从同步上下文中调用异步事物通常是个坏主意。一直做异步,或者为死锁做好准备。例如,您也可以简单地将控制器操作设为异步。

    【讨论】:

    • 在这种特殊情况下,可以从同步代码中以即发即弃的方式调用一些异步内容。
    【解决方案3】:

    如果您需要使用一些发送结果:

        public async IHttpActionResult Post(data)
     {
         var t = Task.Run(() =>_testService.SendEmail(data));
    
         var result = await t;
         // do something with result
     }
    

    - 当然你的 SendEmail 函数应该返回 Task<> 而不是 Task ...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-06
      • 1970-01-01
      • 2015-06-04
      • 2016-07-20
      • 1970-01-01
      • 2015-05-12
      相关资源
      最近更新 更多