[C#] 在 ASP.net Webfrom 中實作 SSE (Server-Sent Events) 但..

2025-08-15

雖然在 .Net 上面用上了 SSE (  Server-Sent Events ) ,但是手上還是有一堆舊專案( Webfrom )要改

所以就改了一下程式碼測試,我想說應該很順利,交給 GPT 後發現,原來還是有些限制的..


前端(切換使用者+建立 SSE)

我做得很簡單:兩個按鈕,按一下就改 Cookie 的 login_user,然後重建 SSE。

<div> <button onclick="loginAs('donma')" type="button">切換為 Donma</button> <button onclick="loginAs('alice')" type="button">切換為 Alice</button> <script> let evt = null; function loginAs(user) { // 寫入 Cookie document.cookie = 'login_user=${user}; path=/;'; console.log("切換身分為:" + user); // 關閉 SSE if (evt) evt.close(); // 建立新的 SSE evt = new EventSource("SSEHandler.ashx"); evt.onmessage = function (e) { console.log("收到伺服器事件:", e.data); }; } </script> </div>

實際專案你一定會換成 JWT、Session、資料庫查詢 但文章的重點在於 證明 WebForm 也能 per-user 推播


後端 SSEHandler,WebForm 不能用 async/await,也不能像 Kestrel 一樣用非同步 IO,所以 SSE 只能靠 Timer 來模擬

<%@ WebHandler Language="C#" Class="SSEHandler" %> using System; using System.Web; public class SSEHandler : IHttpHandler { public void ProcessRequest(HttpContext context) { // 指定 SSE 回應格式 context.Response.ContentType = "text/event-stream; charset=utf-8"; // 關閉輸出緩衝否則資料會卡住,前端會等很久才收到 context.Response.BufferOutput = false; context.Response.Expires = -1; // 禁用快取避免延遲 context.Response.CacheControl = "no-cache"; string user = context.Request.Cookies["login_user"]?.Value ?? "訪客"; // 建立 Timer(每秒 Tick 一次) // 模擬多線呈 var timer = new System.Timers.Timer(1000); timer.Elapsed += (sender, args) => { try { context.Response.Write( $"data: 您好 {user},這是您專屬的 SSE 訊息:{DateTime.Now}\n\n" ); context.Response.Flush(); } catch { // SSE 中斷(例如用戶離開、按 F5 等) timer.Stop(); timer.Dispose(); } }; timer.AutoReset = true; timer.Start(); // 阻塞 Request,不讓 Handler 結束 context.ApplicationInstance.CompleteRequest(); System.Threading.Thread.Sleep(-1); } public bool IsReusable => false; }


結論 - 


雖然實作結果看起來跟之前文章很像,但是請注意,GPT 告訴我說 因為架構上的差異

請不要!請不要!使用在高併發的專案,畢竟這會造成大量 thread 產生,這時候不如改用 AJAX 或是其他技術來做到

這邊是要特別注意的,不過我手上專案都還好還是就繼續用吧..



當麻許的碎念筆記 2014 | Donma Hsu Design.