question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

SignalR Server side InvokeCoreAsync blocks connection when client is not processing result async

See original GitHub issue

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

When calling InvokeCoreAsync from a server side hub it waits for a result to come back from the client.

But when calling multiple InvokeCoreAsync’s to the same client, in parallel, and the client handles the On result call synchronous, it blocks the connection to other calls to the same client.

When the client handles the On result call async, it does not block the connection and you can call multiple InvokeCoreAsync to the same client properly.

Expected Behavior

It should never block the connection to the client.

Steps To Reproduce

Clone https://github.com/rogerfar/signalr-concurrency-test

Run the application (both projects).

The Worker will call all tests in parallel when the client connects.

The Worker in the client project handles the results.

Sync client:

  • Test1 runs after 1s, the client returns after 5s
  • Test2 runs after 2s, the client returns after 1s

Outcome:

  • Test 1 starts
  • Test 1 ends
  • Test 2 starts
  • Test 2 ends

Expected:

  • Test 1 starts
  • Test 2 starts
  • Test 2 ends
  • Test 1 ends

Async client:

  • Test3 runs after 10s, the client returns after 5s
  • Test3 runs after 12s, the client returns after 1s

Outcome:

  • Test 3 start
  • Test 4 start
  • Test 4 end
  • Test 3 end

Exceptions (if any)

No response

.NET Version

7.0.100

Anything else?

I found this old issue referencing a similar issue: https://github.com/dotnet/aspnetcore/issues/10257

But worth noting is that no server/client timeouts occur during this process. Even increasing the time to 1 hour, it will properly keep the connection alive as shown in the trace log.

Issue Analytics

  • State:closed
  • Created 9 months ago
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
rogerfarcommented, Dec 12, 2022

Dispatching is a pretty good solution to this problem. You’re not supposed to block the client’s event loop.

Ok thanks, I figured as much but couldn’t find concrete evidence about it.

BTW @rogerfar this looks like a really cool use case for client results! If you can share, what is the application doing?

Thanks! It has been working very well for us, and now with the server allowing sending to the client and waiting for replies has made it even easier.

We have a product that integrates with all sorts of systems, accounting, customers homebrew, dispatching, maintenance software, basically anything that has some sort of API / SDK. Some are not cloud based like QuickBooks Desktop or Sage50, they have COM API’s or DLL’s.

We create small WPF applications or Windows services that consume these API’s (some SDK’s can’t even run as a service as they need the interactive desktop). These applications are pretty light, they setup a SignalR connection to our server and just sit there and wait, SignalR does all the heavy lifting of reconnecting, keeping alive etc.

The server is basically a command and control, and runs certain code on event loops or timers.

For example if the user submits an Invoice or Purchase Order from our product they see a spinner:

  • Product sends a push request to our integration server with a regular HTTP calls and waits for:
  • Integration server knows that it has an active SignalR connection to the users QuickBooks Desktop
  • Uses SignalR to send the data to the WPF desktop client
  • Server waits for either a positive response or an exception
  • Server returns this response to the user again to the product, spinner closes and shows result

The strong point of using SignalR here is that we always have that reliable persistent connection, no need to mess around with opening firewall ports and very tight control in the sync process.

I’m wanting to write a blog post about it to show the alternative usage of SignalR but I was waiting for .NET7 to incorporate the client result sending.

1reaction
rogerfarcommented, Dec 8, 2022

We use the C# SignalR client as a proxy to various SDK’s like QuickBooksDesktop and Sage50, all those are very simple COM api’s, so no async anywhere.

The server can request data from those API’s which can result in long running tasks, which I have now rewritten to use InvokeCoreAsync, before we used a polling mechanism.

It’s possible that a 2nd task fires while task 1 is still running to the same client, because the SDK’s can handle multiple transactions simultaneously. The issue is that task 2 is blocked until task 1 is complete, which is not desired.

For now, I have wrapped my On events in Tasks:

            _hubConnection.On("DataFetch", async (DataRequest request) =>
            {
                return await Task.Run(() => OnDataRequest(request));
            });

Which works great.

Read more comments on GitHub >

github_iconTop Results From Across the Web

SignalR invoke not returning when used in an async method
I've put a breakpoint in the server method and can confirm that it is being called and returning a value, but for some...
Read more >
Signalr - cant connect to server from client
I had a similar problem that strangely occurred on some computers: the first try fails and the second try works.
Read more >
ASP.NET Core SignalR connection troubleshooting
This error is usually caused by a client using only the WebSockets transport but the WebSocket protocol isn't enabled on the server. Response ......
Read more >
SignalR Troubleshooting
The solution is to stop the SignalR connection before logging the client out. "Uncaught Error: SignalR: jQuery not found. Please ensure jQuery ...
Read more >
Why Asynchronous data with SignalR is Smarter and ...
The server does not block processing between calls while it is collecting data, and can return blocks of information independent of the ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found