Long Polling vs WebSocket in C#: What to Choose for Real-Time?

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Long Call or Eternal Channel: How C# Delivers Data in Real Time

\n\n

Imagine: you're writing a chat in C#. Or a stock trading terminal. Or a notification system. The client is waiting for data — and isn't ready to wait long. In the past, developers made do as best they could: they set timers, polled the server every 5 seconds, and generated unnecessary requests. Today we have two civilized approaches — Long Polling and WebSocket. Both allow the server to send data to the client without an explicit request. But they work fundamentally differently.

\n\n

In this article, we'll look at how to implement both approaches in C# (ASP.NET Core), compare them in terms of speed, load, and complexity, and figure out which one to choose for your project. Let's go.

\n\n

What is Long Polling? (And Why It's Not Magic)

\n\n

Long Polling is an emulation of real-time communication over regular HTTP. The client sends a request to the server, but the server doesn't respond immediately. It keeps the connection open until a new event occurs (or a timeout expires). Once the data is ready, the server sends a response, the client processes it, and immediately opens a new "long" request.

\n\n

This is a clever trick that works on any HTTP server and in any browser. But it comes at a cost: each connection consumes server memory, and if you have thousands of clients, this becomes a problem.

\n\n

Long Polling Example in C# (ASP.NET Core)

\n\n

Let's write a simple controller that simulates a notification queue. The client hits an endpoint, the server waits for new data (e.g., from a Channel<string>) and sends it.

\n\n
using Microsoft.AspNetCore.Mvc;\nusing System.Threading.Channels;\n\n[ApiController]\n[Route("api/[controller]")]\npublic class NotificationsController : ControllerBase\n{\n    private static readonly Channel<string> _channel = Channel.CreateUnbounded<string>();\n\n    // Endpoint for publishing a notification (e.g., from another service)\n    [HttpPost("publish")]\n    public async Task<IActionResult> Publish([FromBody] string message)\n    {\n        await _channel.Writer.WriteAsync(message);\n        return Ok("Notification sent");\n    }\n\n    // Long Polling: client waits until a new message appears\n    [HttpGet("long-poll")]\n    public async Task<IActionResult> LongPoll(CancellationToken cancellationToken)\n    {\n        // Wait for a new message; if none, wait up to 30 seconds\n        using var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);\n        cts.CancelAfter(TimeSpan.FromSeconds(30));\n\n        try\n        {\n            var message = await _channel.Reader.ReadAsync(cts.Token);\n            return Ok(new { data = message });\n        }\n        catch (OperationCanceledException)\n        {\n            // Timeout — return an empty response, client will retry\n            return Ok(new { data = (string?)null });\n        }\n    }\n}\n
\n\n

The client (JavaScript) will look like this:

\n\n
async function startLongPoll() {\n    while (true) {\n        const response = await fetch('/api/notifications/long-poll');\n        const result = await response.json();\n        if (result.data) {\n            console.log('New notification:', result.data);\n        }\n        // Immediately start a new poll\n    }\n}\nstartLongPoll();\n
\n\n

It's simple. But there's a catch: if the server restarts or the client loses the connection, data will be lost. Long Polling does not guarantee delivery.

\n\n

WebSocket: Two-Way Tunnel in C#

\n\n

WebSocket is a full-fledged two-way communication protocol over TCP. After the handshake (a regular HTTP GET with an upgrade), the client and server communicate directly, without the overhead of HTTP headers. The server can send a message at any time, and the client will receive it instantly.

\n\n

In ASP.NET Core, WebSocket is built-in out of the box. No third-party libraries are needed (

Blogs

Book Recommendations