考虑简单的MVC5控制器:
public class DocumentsController {
// ctor code is omitted
[HttpPost, Route("api/documents/request/stamp={stamp}")]
public ActionResult RequestDocuments(string stamp) {
var documents = this.DocumentsRequestService.RequestByStamp(stamp);
return new JsonResult(documents);
}
}
DocumentsRequestService
在内部完成这些事情:
它向专用的 MSMQ-queue 发送请求(让我们称之为 M )并且同步等待传入的消息在 M 的响应队列中:
using(var requestMessage = new Message()) {
requestMessage.Body = documentStamp;
requestMessage.Recoverable = true;
requestMessage.Label = "request";
requestMessage.ResponseQueue = this.requestedDocumentsResponseQueue;
requestMessage.Formatter = new XmlMessageFormatter(new Type[] { typeof(String) });
// send request
this.requestedDocumentsQueue.Send(requestMessage);
// synchronously wait for response
var responseMessage = this.requestedDocumentsResponseQueue.Receive();
if(responseMessage.Label.EndsWith("success")) {
return new DocumentsRequestResult(
success: true,
matches: parseMatchesList(responseMessage)
);
}
return new DocumentsRequestResult(
success: false,
matches: Enumerable.Empty<DocumentsRequestMatch>()
);
}
该邮件的使用者( Windows服务)进行特定的api调用。通过说'具体',我的意思是我们使用第三方手段来做到这一点。这个调用是同步的,而且很长。当处理结束时,消费者向请求消息的响应队列发送响应消息。
从最终用户的角度来看,这个任务应该是阻塞的,或者至少应该看起来像阻塞。
据我所知,运行任务会使用并行化。而使用异步 - 等待对使运行任务异步。如果几个任务并行运行可能会有所帮助。
在我的案例中合并/可能与任务 / 异步合并?如果是,那么我从哪里开始呢?
答案 0 :(得分:4)
&#34;异步&#34;网络呼叫对呼叫者是透明的。对于调用者来说,实现是同步还是异步并不重要。换句话说,从客户的角度来看,它总是异步
。例如,如果RequestDocuments
是同步的或异步的,HTTP客户端就不会关心;无论哪种方式,HTTP客户端都会发送请求并在一段时间后(即异步)接收响应。
同样,HTTP Web服务器并不关心Win32服务是同步实现还是异步实现。它只知道它将消息放入队列中,并且稍后(即异步地)它从队列中获取响应消息。
据我所知,运行Task会使用并行化。而使用async-await对使运行任务异步。
排序。 Task
可用于异步或并行代码,这一事实引起了很多混乱。但是,Parallel
和PLINQ等任务并行库构造牢牢地处于并行(非异步)世界。
如果几个任务并行运行可能会有所帮助。
我相信&#34;同时&#34;这是适当的术语。
首先,请注意ASP.NET免费为您提供了大量的并发性。如果您想在内部并发每个请求,那么您可以通过Task.WhenAll
相当容易地完成此操作。例如,您可以将DocumentsRequestService
调用更改为异步(假设您的消息队列API支持异步调用):
using(var requestMessage = new Message()) {
...
// send request
await this.requestedDocumentsQueue.SendAsync(requestMessage);
// asynchronously wait for response
var responseMessage = await this.requestedDocumentsResponseQueue.ReceiveAsync();
...
}
然后你可以从一个控制器动作同时多次调用它:
public async Task<ActionResult> RequestDocuments(string stamp1, string stamp2) {
var task1 = this.DocumentsRequestService.RequestByStampAsync(stamp1);
var task2 = this.DocumentsRequestService.RequestByStampAsync(stamp2);
var documents = await Task.WhenAll(task1, task2);
return new JsonResult(documents);
}