在 ASP.NET MVC 控制器中以单个方法异步调用多个方法

Calling multiple methods asynchronously in single method in ASP.NET MVC Controller

ASP.NET MVC 应用程序中,我的 Service.cs 中有两个方法,如下所示(为简洁起见简化了方法),我想使用 async 异步调用这些方法。但是从 Controller 调用第一个方法(保存)后,我也想要 return 此操作的结果,而无需等待第二个方法(SendEmail)。但在这种情况下,我必须 return 结果并且不知道如何使用 ASP.NET MVC 异步来管理它。你能给这个场景一些建议吗?我想我必须在所有链方法中使用 async 但不确定如何构建此链。任何帮助,将不胜感激。

控制器:

public JsonResult AddRecord() {
var result = service.Save();
//I need to return the result after record is added (without waiting the email sent)

service.SendEmail();    
}

服务:

public MyEntity Save() {
    //
}


public void SendEmail() {
    //
}

听起来您想从另一个线程调用 SendMail()。 尝试查看对后台作业有帮助的 Hangfire

我能想到的场景。使用匿名任务

public JsonResult AddRecord() {
var result = service.Save();
//I need to return the result after record is added (without waiting the email sent)

Task.Run(() => service.SendEmail()); 
return result;
}

第二种情况是使您的 SendEmail 方法异步,这样它几乎与任务相同,通常它说使用异步方法不是一个好主意,但我认为这种特殊情况符合标准

一种方法是更改​​ SendEmail 的行为及其名称,使其实际上不发送电子邮件。它添加了将电子邮件发送到队列的请求。您的方法调用可能如下所示:

service.QueueEmail(someData);

不需要异步(也没有好处),因为您所做的只是向队列中添加内容。一个单独的进程从队列中读取并发送电子邮件。

这将使您的服务更加专注。知道如何发送电子邮件的更详细的代码将存在于其他地方。然后该代码可以更有效地处理这种复杂性。例如,它可以包含重试逻辑。当您的应用程序中有其他发送电子邮件的进程时,它们可以 re-use 该进程。

你可以试试看:

public class Service
{
    public Task<MyEntity> SaveAsync()
    {
        return Task.Run(() => Save());
    }

    public MyEntity Save()
    {
        Thread.Sleep(2000);
        var entity = new MyEntity();
        return entity;
    }

    public Task SendEmailAsync()
    {
        return Task.Run(() => SendEmail());
    }

    public void SendEmail()
    {
        Thread.Sleep(2000);
        Console.WriteLine("The message is sent");
    }
}

并创建 Controller 或其他服务,有些是这样的:

public class SomeController
{
    private readonly Service _service;

    public SomeController()
    {
        _service = new Service();
    }

    public MyEntity AddRecord()
    {
        var resultTask = _service.SaveAsync();
        _service.SendEmailAsync();

        return resultTask.Result;
    }

    public async Task<MyEntity> AddRecord2()
    {
        var resultTask = _service.SaveAsync();

        _service.SendEmailAsync();

        //var result = await resultTask;
        //return result;

        return await resultTask;
    }
}