When I use signalR which falls back to ServerSentEvents, and I can see on fiddler an open connection to the server waiting for chunked data, does it mean a thread is being occupied on the server at this time?
If so, it is not quite efficient as far as I see it..
For example I would not write such code in the server that blocks a thread:
public ActionResult ServerSentEvents
{
DateTime currentdate = DateTime.Now;
Response.ContentType = "text/event-stream";
while (currentdate.AddMinutes(1) > DateTime.Now)
{
Response.Write(string.Format("data: {0}\n\n", DateTime.Now.ToString()));
Response.Flush();
System.Threading.Thread.Sleep(1000);
}
}
Could it be that SignalR does something more efficiently here?
Your example is very strange. If it was meant like example of totally wrong server code, then its perfect.. ..anyway who handles actual connection (and reading from it) depends on how you host your server (IIS vs self host using Owin).
IIS - im pretty sure there is no thread blocking for each connection. IIS handles reading from socket using something like IO completion ports
Owin\HttpListener - here i'm equally sure SignalR is using async operations for reading from connection (and waiting for data). Which under covers also use IO completion ports.
-> No thread is blocked on server while connection is opened and not receiving data from client...
Yes. (or "Maybe", depending on how SignalR is implemented.)
SSE keeps a socket open between the server and client. You said you wouldn't write code that does
System.Threading.Thread.Sleep(1000);
but it seems efficient enough. When you put a thread to sleep, it stops using a CPU core, and another thread will get its chance to run on the CPU.It is possible SignalR does not use one thread per client connection. It may use a while loop that loops through socket handles, and tries a read on each one in turn, but running in a single thread. (e.g. PHP does not support threads, so if you want to run a multi-client server that is how you do it). Efficiency-wise that is in the same ballpark as using threads. But threads are a low-cost abstraction which generally make the coding a little easier.
It sounds to me like you are doing premature optimization. Unless profiling has shown your bottleneck is the overhead of the context switch as threads are moved on and off the CPU, this is not something to worry about.
That looks like MVC Controller code not SignalR Hub code
Anyway, SignalR supports the async framework in .NET 4.5 so you could return a Task from that method instead and have one background thread handling the wait state and when a task has waited 1000 MS you will continue that task.
You should never ever have
Thread.Sleep
in a requst thread, it kills scalability completely, and its the reason why Frameworks like Entity Framework and ADO.NET supports async operations (A I/O operation like Database is just like aThread.Sleep
)edit: If you for no reason want to use SignalR you can use Tasks from MVC 4 or the AsyncController in MVC 3 and earlier. But I would recommend SignalR since they are doing all the plumbing for you