DrSammyD
DrSammyD

Reputation: 920

MVC AsyncController Blocking

So I've been following along with Steven Sanderson's TechDays Talk on SignalR and ASP.NET Async. I've run into a problem with the following actions

public class SomeController : AsyncController
{
    static TaskCompletionSource<String> _nextMessage
        = new TaskCompletionSource<string>();

    [HttpPost]
    public ActionResult PostMessage(string message)
    {            
        _nextMessage = new TaskCompletionSource<string>();
        oldNextMessage.SetResult(message);
        return Content("success");
    }

    public async void GetMessages()
    {
        Response.ContentType = "text/event-stream";
        while (true)
        {
            var message = await _nextMessage.Task;
            Response.Write("data: " + message + "\n\n");
            Response.Flush();
        }

    }
}

GetMessages seems to be blocking when it is first called, but once it times out, it starts working as expected.

So I load up my javascript which posts and runs GetMessages. On the first call to GetMessages, it hangs (as expected) at

await _nextMessage.Task;

but it won't let me make a call to PostMessage from any where (including other instances of the browser) This is on my dev machine, so it may be a thread issue, but I thought the whole purpose of this was to allow threads to work on multiple things. And that's besides the point that after it times out the first time, it starts to work as expected, where I can post, and get responses immediately. But if I refresh the page, I get the same problem. Any ideas on how to fix this? I'm using Eventsource by the way, but the same problem occurs when I'm doing long polling e.g.

    public async Task<string> GetNextMessage()
    {

        return await _nextMessage.Task;
    }

with a javascript loop function calling GetNextMessage()

Upvotes: 1

Views: 496

Answers (1)

DrSammyD
DrSammyD

Reputation: 920

Here's what I wound up using

[SessionState(SessionStateBehavior.Disabled)]
public class SomeController : AsyncController
{
    static TaskCompletionSource<String> _nextMessage = 
        new TaskCompletionSource<string>();

    public void PostMessage(string message)
    {
        var CreationJObj = FormUtils.AsciiToJObject(Request.Form[0]);
        var CreationObj = FormUtils.FromJObject<MessageDisplayVO>(CreationJObj);
        Parallel.Invoke(() => { _nextMessage.SetResult(CreationObj.Message); });
        _nextMessage = new TaskCompletionSource<string>();

    }

    public async void GetMessages()
    {
        Response.ContentType = "text/event-stream";
        var oldMessage = _nextMessage;
        var message = await oldMessage.Task;
        Response.Write("data: " + message + "\n\n");
        Response.Flush();
    }
}

Upvotes: 1

Related Questions