承接上篇,我們將業務邏輯集中於靜態類別 SessionManager,採用雙字典架構:
CurrentSessionList:Guid -> SessionInfo,追蹤所有活躍 Session。CurrentCallbackList:Guid -> ISessionCallback,維護對應的 Client 回呼通道。靜態建構函式從設定檔讀取 SessionTimeout(分鐘),初始化兩個字典與同步鎖 _syncHelper。
public static Guid StartSession(SessionClientInfo clientInfo)
{
Guid sessionID = Guid.NewGuid();
ISessionCallback callback = OperationContext.Current.GetCallbackChannel<ISessionCallback>();
var sesionInfo = new SessionInfo
{
SessionID = sessionID,
StartTime = DateTime.Now,
LastActivityTime = DateTime.Now,
ClientInfo = clientInfo
};
lock (_syncHelper)
{
CurrentSessionList.Add(sessionID, sesionInfo);
CurrentCallbackList.Add(sessionID, callback);
}
return sessionID;
}
public static void EndSession(Guid sessionID)
{
if (!CurrentSessionList.ContainsKey(sessionID)) return;
lock (_syncHelper)
{
CurrentCallbackList.Remove(sessionID);
CurrentSessionList.Remove(sessionID);
}
}
管理員可強制終止指定 Session,流程:移除 SessionInfo -> 透過 Callback 通知 Client (OnSessionKilled) -> 移除 Callback。因回呼為 One-Way 非同步,鎖持有時間極短,對並發影響微乎其微。
採用 服務端主動輪詢 + 非同步並行 + Callback 協商 設計:
RenewSessions()。CurrentSessionList,若 Now - LastActivityTime < Timeout 則略過。BeginInvoke 非同步呼叫 Client 端 Renew(),並收集 WaitHandle。WaitHandle.WaitAll 等待所有非同步作業完成,最後呼叫 ClearSessions() 清理逾時/已終止項目。[MethodImpl(MethodImplOptions.Synchronized)]
public static void RenewSessions()
{
var waitHandleList = new List<WaitHandle>();
foreach (var session in CurrentSessionList)
{
RenewSession renewsession = delegate(KeyValuePair<Guid, SessionInfo> sessionInfo)
{
if (DateTime.Now - sessionInfo.Value.LastActivityTime < Timeout) return;
try
{
TimeSpan renewDuration = CurrentCallbackList[sessionInfo.Key].Renew();
if (renewDuration.TotalSeconds > 0)
sessionInfo.Value.LastActivityTime += renewDuration;
else
{
sessionInfo.Value.IsTimeout = true;
CurrentCallbackList[sessionInfo.Key].OnSessionTimeout(sessionInfo.Value);
}
}
catch (CommunicationObjectAbortedException)
{
sessionInfo.Value.IsTimeout = true;
}
};
IAsyncResult result = renewsession.BeginInvoke(session, null, null);
waitHandleList.Add(result.AsyncWaitHandle);
}
if (waitHandleList.Count == 0) return;
WaitHandle.WaitAll(waitHandleList.ToArray());
ClearSessions();
}
CommunicationObjectAbortedException 視為 Client 已斷線,直接標記逾時。WaitAll) 後再統一清理字典,避免並發修改集合引發異常。SessionManagementService 僅薄封裝 SessionManager,設定 InstanceContextMode.Single 與 ConcurrencyMode.Multiple 支援高併發。Hosting 端啟動 ServiceHost 並建立 Timer 每 5 秒觸發 RenewSessions()。
SessionUtility 封裝 DuplexChannelFactory 與 Channel 生命週期。重點在 SessionCallback 實作:
public class SessionCallback : ISessionCallback
{
public TimeSpan Renew()
{
return SessionUtility.Timeout - (DateTime.Now - SessionUtility.LastActivityTime);
}
public void OnSessionKilled(SessionInfo info)
{
MessageBox.Show("Session 已被強制終止!", info.SessionID.ToString());
Application.Exit();
}
public void OnSessionTimeout(SessionInfo info)
{
MessageBox.Show("Session 逾時!", info.SessionID.ToString());
Application.Exit();
}
}
Renew() 根據「上次滑鼠移動時間」動態計算剩餘可延長時間。Form 載入時遞迴註冊所有控制項的 MouseHover 事件更新 LastActivityTime,完美模擬使用者活躍度。
此架構展示 WCF 雙向通訊在分散式 Session 管理的強大威力:服務端掌握主動權,透過非同步輪詢與 Callback 協商實現即時、可擴展的 Session 生命週期控制,完美解決傳統 Client 輪詢模式的即時性與效能難題。