Web服务意外地同步运行

我们有一个需要连接到慢速数据库进程并将值返回给客户端的Web服务,因此尝试异步运行它以阻止它阻塞线程。 但是,如果我们进行两次调用,它们会按顺序运行,而不是异步运行。 呼叫1在5秒后返回,在10后呼叫2,在15后呼叫3,依此类推。

这是(简化测试版)代码 –

public class ImportAsyncController : AsyncController { [HttpPost] [Authorize(Roles = "Admin, ContentAdmin, ContentEdit")] public async Task SlowProcess() { await Task.Delay(5000); return "Hello, world!"; } } 

IIS 7.5,默认设置。 遗产项目所以并非完全不可能,项目文件中的某些内容会强制它,但不知道是什么,抱歉。

作为参考,从中调用的实际代码调用SQL服务器sproc。 它在内部使用sp_getapplock进行并发逻辑,并在SSMS中运行时正确返回 – 调用1运行完成,如果调用1仍在运行,则调用> 1返回错误代码,否则返回自身完成。 那个逻辑很好; 问题实际上是在队列中按顺序处理Web请求,因此在调用1完成之前,甚至不会调用call> 1。

我们做错了什么?

如果您正在写入会话,则可能会发生这种情况。 基本上,Session对象将被锁定,直到请求完成,这给出了同步调用的错觉。

由于以下Action写入会话,它将锁定会话对象,直到请求完成(5秒后)。 如果您从客户端调用此操作异步,它将在5秒,10秒,15秒等后返回。

 public async Task SlowProcess() { Session["Hello"] = "World"; await Task.Delay(5000); return "Hello, world!"; 

}

如果需要使用会话对象,可以告诉控制器使用ReadOnly模式,这样可以防止会话被锁定。 要执行此操作,请使用控制器上的SessionStateBehaviour属性(不是操作)。

你会有这样的东西……

 [SessionState(System.Web.SessionState.SessionStateBehavior.ReadOnly)] public class HomeController : Controller { public async Task SlowProcess() { Session["Hello"] = "World"; await Task.Delay(5000); return "Hello, world!"; } } 

希望这可以帮助。

更新

我找到了一篇很好的文章,解释了你可能觉得有用的问题。 看看这个!

http://johnculviner.com/asp-net-concurrent-ajax-requests-and-session-state-blocking/