Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

Async void not supported on websockets #656

Closed
sassame opened this Issue Sep 7, 2012 · 11 comments

Comments

Projects
None yet
4 participants

sassame commented Sep 7, 2012

I think there's an issue with firing a function prototyped with public async void from within a hub. I've created a sample project that demonstrates, but at a high level, here's the important code:

 public class SearchHub : Hub
    {
        public string Works(string query)
        {

            var service = new SearchService();
            var t1 = new Task(() => service.DoSearch((m, n) => Update(m, n), Context.ConnectionId));
            t1.Start();
            return "true";
        }

        public string Fails(string query)
        {

            var service = new SearchService();

            //This should act like a fire and forget call...?
            service.DoSearch((m, n) => Update(m, n), Context.ConnectionId);
            return "true";
        }

        public async Task<string> AlsoFails(string query)
        {

            var service = new SearchService();

            //This should act like a fire and forget call...?
            service.DoSearch((m, n) => Update(m, n), Context.ConnectionId);
            return "true";
        }

        private void Update(IList<string> updateList, string connectionID)
        {
            Clients[connectionID].update(updateList);
        }
    }

    public class SearchService
    {
        public async void DoSearch(Action<IList<string>, string> action, string userID)
        {
            var t1 = new Task(() => Pause(100, 1, action, userID));
            var t2 = new Task(() => Pause(1000, 4, action, userID));
            var t3 = new Task(() => Pause(1500, 7, action, userID));

            t1.Start();
            t2.Start();
            t3.Start();
        }

        private async void Pause(int time, int countStart, Action<IList<string>, string> action, string userID)
        {
            await Task.Delay(time);
            //System.Threading.Thread.Sleep(time);
            var arr1 = new List<string>() { "test" + countStart, "test" + (countStart + 1), "test" + (countStart + 2) };
            action(arr1, userID);
        }
    }

sassame commented Sep 7, 2012

BTW, no idea if this is a problem with SignalR or the new framework.

Owner

davidfowl commented Oct 21, 2012

The repro is way simpler:

public class MyHub : Hub
{
      public async void Method()
      {
      }
}

@ghost ghost assigned davidfowl Oct 21, 2012

sassame commented Oct 21, 2012

:) Well, yeah, but I wanted to be thorough, the important thing is that even when you have a normal method that calls an async method, you get a crash (subtly different than the example you posted, but probably related). This is an important case since it's very tough to debug, took me a long time to figure out the crash was related to SignalR (since the method itself looks so normal).

Thanks!

Owner

davidfowl commented Oct 21, 2012

Seems it's related to websockets and how ASP.NET treats async void methods.

Owner

davidfowl commented Oct 22, 2012

Here's a repro with raw ASP.NET outside of SignalR https://github.com/davidfowl/WebSocketAsyncVoidBug

Owner

davidfowl commented Oct 23, 2012

Async void doesn't work in websockets so we're not going to fix this issue.

@davidfowl davidfowl closed this Oct 23, 2012

nitinag commented Dec 9, 2012

To make it easier to find in search, the exception that occurs is:
System.InvalidOperationException: An asynchronous module or handler completed while an asynchronous operation was still pending.

Current workaround/solution (as per above comments) is to have the method return a value instead of using void.

Owner

davidfowl commented Dec 9, 2012

@nitinag That's actually not the exception you should be seeing as a result of this.

nitinag commented Dec 9, 2012

@davidfowl My repo is below. It occurs even when not using websockets. What could be causing this? The same solution here resolved the issue.

public class MyHub : Hub
{
      public async void Method()
      {
          await Task.Delay(2000);
      }
}
Owner

davidfowl commented Dec 9, 2012

That's actually a different exception but I can see why it would happen using the same pattern.

wasabii commented Sep 9, 2014

I want to point out that this is causing weird issues with my Hubs. I'm trying to use Observable to subscribe to some events from OnConnected, and then Dispose the subscription in OnDisconnected when I'm done.

This error get's throw on the Dispose. Which is kind of silly. Internally, somewhere, Observable is probably trying to schedule a void Task. I don't see why this shouldn't work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment