首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C# Timer 控件能否共用?考試系統多用戶計時的正確實現

     編輯:程式設計綜合問答

一個 Timer 只能幹一件事

`System.Windows.Forms.Timer` 或 `System.Timers.Timer` 本質上都是單一觸發源:一個 Timer 實例只能綁定一個 `Interval` 和一個 `Elapsed`/`Tick` 事件處理器。若嘗試讓多個用戶共用同一個 Timer 實例,會導致計時邏輯混亂、互相干擾。

解決方案:單一 Timer + 用戶登錄時間表

採用一個全局 Timer + 數據結構記錄每個用戶的開始時間的模式:

// 伪代码示例
private readonly Dictionary<string, DateTime> _userLoginTime = new Dictionary<string, DateTime>();
private readonly System.Timers.Timer _globalTimer = new System.Timers.Timer(60_000); // 每分鐘檢查一次

public void UserLogin(string userId)
{
    _userLoginTime[userId] = DateTime.Now;
    if (!_globalTimer.Enabled) _globalTimer.Start();
}

private void OnTimerElapsed(object sender, ElapsedEventArgs e)
{
    var now = DateTime.Now;
    var expiredUsers = _userLoginTime
        .Where(kvp => (now - kvp.Value).TotalHours >= 2)
        .Select(kvp => kvp.Key)
        .ToList();

    foreach (var userId in expiredUsers)
    {
        NotifyUserTimeUp(userId); // 發送提醒、自動交卷等
        _userLoginTime.Remove(userId);
    }

    if (_userLoginTime.Count == 0) _globalTimer.Stop();
}

關鍵點

  • Timer 間隔:設為 1 分鐘或更短,平衡精度與性能;
  • 線程安全:若涉及多線程訪問字典,請用 `ConcurrentDictionary` 或加鎖;
  • 持久化:若需應對進程重啟,將登錄時間存入資料庫或 Redis;
  • 高精度需求:若需秒級觸發,可改用 `Task.Delay` 輪詢或專門的調度庫(Quartz.NET、Hangfire)。

總結

不要試圖讓一個 Timer 實例同時服務多個獨立計時任務。改用集中式輪詢 + 用戶狀態表,代碼更清晰、擴展性更強、避免競態條件。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved