在 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;
}
}
在 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;
}
}