我正在尝试在异步控制器中执行异步操作。我需要做的就是当我按下视图中的按钮时,它会给我一个警报,指示已完成工作。当工作完成后,我可以做一些事情(例如,返回一个json或重定向到另一个视图)。这是我的代码:
服务器端:
public void DoWork()
{
var a = MakeADelay();
}
public async Task<ActionResult> MakeADelay()
{
await Task.Delay(5000);
return RedirectToAction("UploadComplete");
}
public ActionResult UploadComplete()
{
return View();
}
这是我的客户端代码:
$("#btnAsync").click(function () {
$.ajax({
url: '/Upload/DoWork',
type: "post",
success: function () {
alert("Work in Progress!!");
}
});
});
当这段代码运行时,所有代码似乎都按预期执行,但是当服务器端代码到达语句return RedirectToAction("UploadComplete");
时,它什么也没做!我认为它在另一个线程或其他东西中运行。
问题是什么?
第二个问题是异步行为究竟意味着什么?我从不希望我的行动等待声明完成。我总是希望我的行为将作业发送到执行队列并返回到客户端,当作业完成后,我可以通过某种方式通知客户端。我怎样才能通知客户?用SignalR什么的?
答案 0 :(得分:1)
问题是什么?
就在这里:
public void DoWork()
{
var a = MakeADelay();
}
这样做是启动MakeADelay
然后立即返回其调用者,这可能会完成创建响应并发送它。
延迟完成后,您的MakeADelay
会尝试通过拨打RedirectToAction
继续执行。但是,该请求的响应已经发送,因此这很可能会导致异常(由于您从未await
任务a
,因此将被忽略。或者也许它不会做任何事情,但它当然不会做的是回到过去并重写已经发送的响应。
第二个问题是异步行为实际意味着什么?
我有一个你可能觉得有用的introduction on the subject。我还在我的博客上描述了async
does not change the HTTP protocol - 你仍然只收到每个请求的一个回复。你要做的是为一个请求发送两个响应,这是行不通的。
我总是希望我的操作将作业发送到执行队列并返回到客户端,当作业完成后,我可以通过某种方式通知客户端。我怎样才能通知客户?有SignalR还是什么?
然后你需要一个队列。我推荐一些具有持久性保证的进程外的东西。例如,Azure队列,MSMQ,WebSphere MQ等
而且,是的,您可以使用SignalR进行通知。我推荐这个。