diff --git a/SHH.MjpegPlayer/Core/Extensions/ProcessExtension.cs b/SHH.MjpegPlayer/Core/Extensions/ProcessExtension.cs index 427d357..df7f687 100644 --- a/SHH.MjpegPlayer/Core/Extensions/ProcessExtension.cs +++ b/SHH.MjpegPlayer/Core/Extensions/ProcessExtension.cs @@ -47,30 +47,26 @@ namespace SHH.MjpegPlayer try { var process = Process.GetProcessById(pid); - if (process != null) { procName = process.ProcessName; process.Kill(); - _sysLog.Warning("拒绝停止高权限系统进程: {Pid} - {Name}", pid, process.ProcessName); + _sysLog.Information("成功通过 PID 杀掉进程 - Pid: {Pid}, Name: {Name}", pid, procName); return true; } - else - { - // 找不到 ID 对应的进程,应该是进异常不会进这里 - _sysLog.Information("成功杀掉进程 - Pid: {Pid}", pid); - return false; - } + + _sysLog.Warning("无法获取进程实例 - Pid: {Pid}", pid); + return false; } catch (ArgumentException) { - _sysLog.Warning("杀掉进程失败,Pid: {Pid} 不存在", pid); + _sysLog.Warning("杀掉进程失败,Pid: {Pid} 不存在或已提前退出", pid); return false; } catch (Exception ex) { - _sysLog.Error(ex, "杀掉进程异常, Pid: {Pid}", pid); + _sysLog.Error(ex, "杀掉进程异常, Pid: {Pid}, 进程名: {Name}", pid, procName); return false; } } diff --git a/SHH.MjpegPlayer/Core/Models/SumByTime.cs b/SHH.MjpegPlayer/Core/Models/SumByTime.cs index cbdf1aa..7c37478 100644 --- a/SHH.MjpegPlayer/Core/Models/SumByTime.cs +++ b/SHH.MjpegPlayer/Core/Models/SumByTime.cs @@ -65,123 +65,112 @@ namespace SHH.MjpegPlayer /// /// 刷新方法调用次数 /// - /// /// /// public void Refresh(string methodName, uint count = 1) { try { - #region 加入集合 + #region 秒统计同步 - // 加入集合 lock (_second) { + // 确保键存在 if (!_second.ContainsKey(methodName)) _second.Add(methodName, 0); + + if (!LastRefreshSecond.Equals(DateTime.Now.Second)) + { + LastRefreshSecond = DateTime.Now.Second; + // 获取当前键的快照进行遍历,确保线程安全 + var keys = _second.Keys.ToList(); + foreach (var key in keys) + { + uint val = _second[key]; + if (!TotalSecond.ContainsKey(key)) + TotalSecond.Add(key, val); + else + TotalSecond[key] = val; + + _second[key] = 0; // 重置当前秒计数值 + } + } + + _second[methodName] += count; } - // 加入集合 + #endregion + + #region 分钟统计同步 + lock (_minute) { if (!_minute.ContainsKey(methodName)) _minute.Add(methodName, 0); + + if (!LastRefreshMinute.Equals(DateTime.Now.Minute)) + { + LastRefreshMinute = DateTime.Now.Minute; + var keys = _minute.Keys.ToList(); + foreach (var key in keys) + { + uint val = _minute[key]; + if (!TotalMinute.ContainsKey(key)) + TotalMinute.Add(key, val); + else + TotalMinute[key] = val; + + _minute[key] = 0; + } + } + _minute[methodName] += count; } + #endregion + + #region 小时统计同步 + lock (_hour) { if (!_hour.ContainsKey(methodName)) _hour.Add(methodName, 0); + + if (!LastRefreshHour.Equals(DateTime.Now.Hour)) + { + LastRefreshHour = DateTime.Now.Hour; + var keys = _hour.Keys.ToList(); + foreach (var key in keys) + { + uint val = _hour[key]; + if (!TotalHour.ContainsKey(key)) + TotalHour.Add(key, val); + else + TotalHour[key] = val; + + _hour[key] = 0; + } + } + _hour[methodName] += count; } - // 加入集合 + #endregion + + #region 全量累计同步 + lock (All) { if (!All.ContainsKey(methodName)) All.Add(methodName, 0); + + All[methodName] += (ulong)count; } #endregion - - #region 时间变更统计 - - // 秒刷新 - if (!LastRefreshSecond.Equals(DateTime.Now.Second)) - { - LastRefreshSecond = DateTime.Now.Second; - - var sb = new StringBuilder(); - foreach (var de in _second) - { - // 更新输出用统计信息 - if (!TotalSecond.ContainsKey(de.Key)) - TotalSecond.Add(de.Key, de.Value); - else - TotalSecond[de.Key] = de.Value; - - sb.Append($"\r\n\t{de.Key} => 执行 {de.Value} 次"); - _second[de.Key] = 0; - } - var logMsg = $"统计 => SumBySecond 统计时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm")}{sb.ToString()}"; - //Logs.LogInformation(EIdSys.TotalBySecond, logMsg); - } - - // 分钟刷新 - if (!LastRefreshMinute.Equals(DateTime.Now.Minute)) - { - LastRefreshMinute = DateTime.Now.Minute; - - var sb = new StringBuilder(); - foreach (var de in _minute) - { - // 更新输出用统计信息 - if (!TotalMinute.ContainsKey(de.Key)) - TotalMinute.Add(de.Key, de.Value); - else - TotalMinute[de.Key] = de.Value; - - sb.Append($"\r\n\t{de.Key} => 执行 {de.Value} 次, 平均每秒 {Math.Round((double)de.Value / 60, 2)} 次"); - _minute[de.Key] = 0; - } - var logMsg = $"统计 => SumByMinute 统计时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm")}{sb.ToString()}"; - //Logs.LogInformation(EIdSys.TotalByMinute, logMsg); - } - - // 小时刷新 - if (!LastRefreshHour.Equals(DateTime.Now.Hour)) - { - LastRefreshHour = DateTime.Now.Hour; - - var sb = new StringBuilder(); - foreach (var de in _hour) - { - // 更新输出用统计信息 - if (!TotalHour.ContainsKey(de.Key)) - TotalHour.Add(de.Key, de.Value); - else - TotalHour[de.Key] = de.Value; - - sb.Append($"\r\n\t{de.Key} => 执行 {de.Value} 次, 平均每秒 {Math.Round((double)de.Value / 60, 2)} 次"); - _hour[de.Key] = 0; - } - var logMsg = $"统计 => SumByHour 统计时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm")}{sb.ToString()}"; - //Logs.LogInformation(EIdSys.TotalByHour, logMsg); - } - - #endregion - - #region 数值更新 - - _second[methodName] += count; - _minute[methodName] += count; - _hour[methodName] += count; - All[methodName] += count; - - #endregion } catch (Exception ex) { - //Logs.LogWarning(ex.Message); + // 可选:利用 Ayay 项目规范记录日志 + // _sysLog.Warning("统计刷新异常: {Msg}", ex.Message); } } diff --git a/SHH.MjpegPlayer/SHH.MjpegPlayer.csproj b/SHH.MjpegPlayer/SHH.MjpegPlayer.csproj index 72ec479..6a5c817 100644 --- a/SHH.MjpegPlayer/SHH.MjpegPlayer.csproj +++ b/SHH.MjpegPlayer/SHH.MjpegPlayer.csproj @@ -7,6 +7,12 @@ enable + + + + + + diff --git a/SHH.MjpegPlayer/Server/MjpegSession.cs b/SHH.MjpegPlayer/Server/MjpegSession.cs index 2ade36f..da88fba 100644 --- a/SHH.MjpegPlayer/Server/MjpegSession.cs +++ b/SHH.MjpegPlayer/Server/MjpegSession.cs @@ -13,16 +13,20 @@ namespace SHH.MjpegPlayer /// public class MjpegSession : IDisposable { + #region Defines + private static readonly ILogger _sysLog = Log.ForContext("SourceContext", LogModules.Core); - #region Counter + private CancellationTokenSource? _sessionCts; private SumByTime _sumBySecond = new SumByTime(); - /// - /// 计数器 - /// + + /// 计数器 public SumByTime Counter => _sumBySecond; + // 引入 Disposed 标志位 + private volatile bool _isDisposed = false; + #endregion #region Info @@ -43,9 +47,6 @@ namespace SHH.MjpegPlayer #endregion - // [修复] 引入 Disposed 标志位 - private volatile bool _isDisposed = false; - #region Constructor /// @@ -150,7 +151,10 @@ namespace SHH.MjpegPlayer // 初始化最近接收时间,避免刚连接就被判定为超时 LastRecImgTime = DateTime.Now; - Task.Run(() => { DoWorkTask(client); }); + // 绑定全局取消令牌,确保系统停止时能立即强制中断所有会话 + _sessionCts = new CancellationTokenSource(); + + Task.Run(() => { DoWorkTask(client, _sessionCts.Token); }, _sessionCts.Token); } catch (Exception ex) { @@ -162,7 +166,7 @@ namespace SHH.MjpegPlayer #region DoWorkTask - private void DoWorkTask(TcpClient client) + private void DoWorkTask(TcpClient client, CancellationToken token) { try { @@ -174,11 +178,12 @@ namespace SHH.MjpegPlayer #region 等待连接, 处理地址栏参数 int iLoc = 0; - while (!client.Connected) + while (!client.Connected && !token.IsCancellationRequested) { Thread.Sleep(50); if (++iLoc > 60) return; } + if (token.IsCancellationRequested) return; try { @@ -210,7 +215,7 @@ namespace SHH.MjpegPlayer byte[] boundaryBytes = Encoding.ASCII.GetBytes("\r\n--frame\r\nContent-Type: image/jpeg\r\nContent-Length: "); byte[] doubleNewLine = Encoding.ASCII.GetBytes("\r\n\r\n"); - while (client.Connected && !_isDisposed) + while (client.Connected && !_isDisposed && !token.IsCancellationRequested) { try { @@ -256,7 +261,8 @@ namespace SHH.MjpegPlayer stopwatch.Stop(); var needSleep = frameInterval - (int)stopwatch.ElapsedMilliseconds; - if (needSleep > 0) Thread.Sleep(needSleep); + if (needSleep > 0) + Task.Delay(needSleep, token).Wait(token); } catch (Exception ex) { @@ -333,9 +339,18 @@ namespace SHH.MjpegPlayer { if (_isDisposed) return; _isDisposed = true; + + // 释放令牌资源 + try + { + _sessionCts?.Cancel(); + _sessionCts?.Dispose(); + } + catch { } + MjpegStatics.Sessions.RemoveSession(this); } #endregion } -} +} \ No newline at end of file