|
@@ -160,17 +160,56 @@ namespace ivf_tl_Operate
|
|
|
/// <param name="sender"></param>
|
|
/// <param name="sender"></param>
|
|
|
/// <param name="e"></param>
|
|
/// <param name="e"></param>
|
|
|
/// <exception cref="NotImplementedException"></exception>
|
|
/// <exception cref="NotImplementedException"></exception>
|
|
|
|
|
+ // === 日志洪流抑制(防 8GB 复发)===
|
|
|
|
|
+ // WPF 布局类异常被下面 e.Handled=true 吞掉后,WPF 会逐帧重新测量→同一异常每帧重抛。
|
|
|
|
|
+ // 无节流时同一条异常每秒上千次、每条带完整堆栈(~4.7KB),曾致单日日志涨到 8GB。
|
|
|
|
|
+ // 此处按异常签名节流:同签名 10s 内只放行一条,下次放行时补记期间被抑制的条数。
|
|
|
|
|
+ private static readonly object _logThrottleLock = new object();
|
|
|
|
|
+ private static readonly Dictionary<string, long[]> _logThrottle = new Dictionary<string, long[]>(); // signature -> [lastTicks, suppressedCount]
|
|
|
|
|
+ private static readonly long _logThrottleWindowTicks = TimeSpan.FromSeconds(10).Ticks;
|
|
|
|
|
+
|
|
|
|
|
+ /// <summary>
|
|
|
|
|
+ /// 节流判定:同 <paramref name="signature"/> 在窗口期(10s)内只放行一次。
|
|
|
|
|
+ /// 返回 true=应记录(<paramref name="suppressNote"/> 含上一窗口被抑制的条数提示);false=抑制本条。线程安全。
|
|
|
|
|
+ /// </summary>
|
|
|
|
|
+ private static bool ShouldLogThrottled(string signature, out string suppressNote)
|
|
|
|
|
+ {
|
|
|
|
|
+ suppressNote = string.Empty;
|
|
|
|
|
+ long now = DateTime.Now.Ticks;
|
|
|
|
|
+ lock (_logThrottleLock)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (_logThrottle.TryGetValue(signature, out long[] st))
|
|
|
|
|
+ {
|
|
|
|
|
+ if (now - st[0] < _logThrottleWindowTicks)
|
|
|
|
|
+ {
|
|
|
|
|
+ st[1]++; // 仍在窗口内:累计被抑制条数,不记录
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (st[1] > 0) suppressNote = $"(前 10s 抑制 {st[1]} 条相同异常)";
|
|
|
|
|
+ st[0] = now;
|
|
|
|
|
+ st[1] = 0;
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ _logThrottle[signature] = new long[] { now, 0 };
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
private void App_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
|
|
private void App_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
|
|
|
{
|
|
{
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
try
|
|
try
|
|
|
{
|
|
{
|
|
|
- if (e.Exception.InnerException != null)
|
|
|
|
|
|
|
+ // 按异常消息节流(布局类异常被吞后会逐帧重抛,见上方说明)。
|
|
|
|
|
+ if (ShouldLogThrottled("UI:" + (e.Exception?.Message ?? "null"), out string note))
|
|
|
{
|
|
{
|
|
|
- Log4netHelper.WriteLog($"UI线程异常详细:{e.Exception.InnerException.Message}{e.Exception.InnerException.StackTrace}");
|
|
|
|
|
|
|
+ if (e.Exception.InnerException != null)
|
|
|
|
|
+ {
|
|
|
|
|
+ Log4netHelper.WriteLog($"UI线程异常详细:{e.Exception.InnerException.Message}{e.Exception.InnerException.StackTrace}");
|
|
|
|
|
+ }
|
|
|
|
|
+ Log4netHelper.WriteLog($"UI线程异常{note}:{e.Exception.Message}{e.Exception.StackTrace}");
|
|
|
}
|
|
}
|
|
|
- Log4netHelper.WriteLog($"UI线程异常:{e.Exception.Message}{e.Exception.StackTrace}");
|
|
|
|
|
- //把 Handled 属性设为true,表示此异常已处理,程序可以继续运行,不会强制退出
|
|
|
|
|
|
|
+ //把 Handled 属性设为true,表示此异常已处理,程序可以继续运行,不会强制退出
|
|
|
}
|
|
}
|
|
|
catch (Exception ex)
|
|
catch (Exception ex)
|
|
|
{
|
|
{
|