Web service running unexpectedly synchronously

自古美人都是妖i 提交于 2019-12-23 05:05:42

问题


We've got a web service that needs to connect to a slow database process and returns a value to the client, so are trying to run it asynchronously to stop it blocking the thread. However, if we make two calls they run sequentially, not asynchronously at all. Call 1 returns after 5 seconds, call 2 after 10, call 3 after 15 and so on.

Here's the (simplified test version) code -

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

IIS 7.5, default settings. Legacy project so not completely impossible there's something elsewhere in the project file that's forcing it but no idea what, sorry.

For reference the real code that this was cut down from calls an SQL server sproc. That has concurrency logic internally using sp_getapplock and returns correctly when run in SSMS - call 1 runs to completion, call >1 returns an error code if call 1 is still running or itself completes if it is not. That logic is fine; the problem really is that the web requests are being processed sequentially in a queue so call >1 isn't even called until call 1 has completed.

What are we doing wrong?


回答1:


This can happen if you action is writing to the Session. Basically the Session object will be locked until the request is finished which gives the illusion of a synchronous call.

Example

Since the following Action writes to the session it will lock the session object until the request has finished (after 5 seconds). If you were to calls this action async from the client it would return after 5 seconds, 10 seconds, 15 seconds etc.

public async Task<string> SlowProcess() {

    Session["Hello"] = "World";

    await Task.Delay(5000);
    return "Hello, world!"; 

}

Solution

If you need to use the session object you can tell the controller to use ReadOnly mode which should prevent the session being locked. To do this you use the SessionStateBehaviour attribute on the controller (Not the action).

You will have something that looks like this...

[SessionState(System.Web.SessionState.SessionStateBehavior.ReadOnly)]
public class HomeController : Controller
{


    public async Task<string> SlowProcess()
    {

        Session["Hello"] = "World";

        await Task.Delay(5000);
        return "Hello, world!";
    }


}

Hope this helps.

Update

I found a good article which explains the issue that you might find useful. Check it out!

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



来源:https://stackoverflow.com/questions/33913227/web-service-running-unexpectedly-synchronously

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!