简体   繁体   English

如何从非异步 web API 调用异步方法

[英]How call async method from non async web API

I am having web api, which is non async.我有 web api,这是非异步的。

From that web api, i am calling method从那个web api,我正在调用方法

SmtpClient.SendMailAsync(email); SmtpClient.SendMailAsync(电子邮件);

This email get sent to respective person, but the next web api request get fails.这个 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)
     }
}

From the days before the async/await pattern was introduced, there are still many non-asychronous functions around in Framework classes.从引入异步/等待模式之前的日子开始,框架类中仍然存在许多非异步函数。

SmtpClient client is one of the classes old enough for this. SmtpClient 客户端是足够老的类之一。 The SendFunction are the droids you are look for: SendFunction 是您正在寻找的机器人:

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

While the naming is a bit off and they return void, those seems to be the pre-async functions.虽然命名有点偏离并且它们返回 void,但这些似乎是预异步函数。 Failure should be communicated via Exceptions in both cases.在这两种情况下,都应该通过异常来传达失败。

Given your comment that you want to have SendEmail behave like fire & forget, I would propose using鉴于您希望 SendEmail 表现得像火并忘记的评论,我建议使用

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

This will give the unit of work to the threadpool and free your request from the duty of waiting for this task.这会将工作单元分配给线程池,并将您的请求从等待此任务的职责中解放出来。 Generelly this is advised for fire & forget.一般来说,这被建议用于火灾和忘记。

As a rule of thumb otherwise, it's generally a bad idea to call asynchronous things from a synchronous context.根据经验,从同步上下文中调用异步事物通常是个坏主意。 Do async all the way, or be prepared for deadlocking.一直做异步,或者为死锁做好准备。 For example, you could simply make your controller actions asynchronous as well.例如,您可以简单地使您的 controller 操作也异步。

If you will need use some result of sending:如果您需要使用一些发送结果:

    public async IHttpActionResult Post(data)
 {
     var t = Task.Run(() =>_testService.SendEmail(data));

     var result = await t;
     // do something with result
 }

- but of course your SendEmail function should return Task<> instead of Task ... - 当然你的 SendEmail function 应该返回Task<>而不是Task ...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM