修复监控bug
This commit is contained in:
@@ -33,12 +33,12 @@ namespace UIShare.GlobalVariable
|
||||
|
||||
/// <summary>
|
||||
/// 已注册的采样项:(Fingerprint, MethodName, 编译后的委托, DeviceInstance)
|
||||
/// 委托签名统一为 Func<object, CancellationToken, Task<string>>
|
||||
/// 委托签名统一为 Func<object, CancellationToken, Task<double>>
|
||||
/// - 第一个参数 = 设备实例(open delegate 风格,编译时已做类型转换)
|
||||
/// - 第二个参数 = CancellationToken(无参方法会忽略它)
|
||||
/// - 返回值 = Task<string>
|
||||
/// - 返回值 = Task<double>(Task<string> 方法自动 TryParse 为 double)
|
||||
/// </summary>
|
||||
private readonly List<(string Fingerprint, string MethodName, Func<object, CancellationToken, Task<string>> Invoker, object Device)> _registeredMethods = new();
|
||||
private readonly List<(string Fingerprint, string MethodName, Func<object, CancellationToken, Task<double>> Invoker, object Device)> _registeredMethods = new();
|
||||
|
||||
private CancellationTokenSource? _cts;
|
||||
private bool _disposed;
|
||||
@@ -76,11 +76,13 @@ namespace UIShare.GlobalVariable
|
||||
|
||||
/// <summary>
|
||||
/// 将 MethodInfo 编译为强类型委托,后续调用零反射开销。
|
||||
/// 统一签名为 Func<object, CancellationToken, Task<string>>:
|
||||
/// 统一签名为 Func<object, CancellationToken, Task<double>>:
|
||||
/// - Task<double> 方法:直接返回 double 值
|
||||
/// - Task<string> 方法:自动 TryParse 为 double
|
||||
/// - 无参方法:忽略 CancellationToken
|
||||
/// - 带 CancellationToken 方法:直接透传
|
||||
/// </summary>
|
||||
private static Func<object, CancellationToken, Task<string>> BuildInvoker(MethodInfo method)
|
||||
private static Func<object, CancellationToken, Task<double>> BuildInvoker(MethodInfo method)
|
||||
{
|
||||
var deviceParam = Expression.Parameter(typeof(object), "device");
|
||||
var ctParam = Expression.Parameter(typeof(CancellationToken), "ct");
|
||||
@@ -96,8 +98,24 @@ namespace UIShare.GlobalVariable
|
||||
|
||||
var call = Expression.Call(castDevice, method, callArgs);
|
||||
|
||||
return Expression.Lambda<Func<object, CancellationToken, Task<string>>>(
|
||||
call, deviceParam, ctParam).Compile();
|
||||
if (method.ReturnType == typeof(Task<double>))
|
||||
{
|
||||
// Task<double> 方法:直接返回
|
||||
return Expression.Lambda<Func<object, CancellationToken, Task<double>>>(
|
||||
call, deviceParam, ctParam).Compile();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Task<string> 方法:await 后 TryParse 为 double
|
||||
return async (device, ct) =>
|
||||
{
|
||||
// 通过 MethodInfo.Invoke 调用(仅 Task<string> 路径,性能可接受)
|
||||
var task = (Task<string>)method.Invoke(device,
|
||||
parms.Length == 1 ? new object[] { ct } : Array.Empty<object>())!;
|
||||
string raw = await task.ConfigureAwait(false);
|
||||
return double.TryParse(raw, out double v) ? v : double.NaN;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -126,7 +144,9 @@ namespace UIShare.GlobalVariable
|
||||
.Where(m =>
|
||||
{
|
||||
if (m.GetCustomAttribute<MonitorableAttribute>() == null) return false;
|
||||
if (m.ReturnType != typeof(Task<string>)) return false;
|
||||
// 同时支持 Task<string> 和 Task<double> 返回类型
|
||||
var rt = m.ReturnType;
|
||||
if (rt != typeof(Task<string>) && rt != typeof(Task<double>)) return false;
|
||||
var parms = m.GetParameters();
|
||||
return parms.Length == 0 ||
|
||||
(parms.Length == 1 && parms[0].ParameterType == typeof(CancellationToken));
|
||||
@@ -184,10 +204,10 @@ namespace UIShare.GlobalVariable
|
||||
{
|
||||
try
|
||||
{
|
||||
// 直接委托调用,零反射开销
|
||||
string raw = await entry.Invoker(entry.Device, token).ConfigureAwait(false);
|
||||
// 直接委托调用,零反射开销(Task<double> 路径)或自动 TryParse(Task<string> 路径)
|
||||
double value = await entry.Invoker(entry.Device, token).ConfigureAwait(false);
|
||||
|
||||
if (!double.TryParse(raw, out double value)) return;
|
||||
if (double.IsNaN(value)) return;
|
||||
|
||||
// 采样成功,重置失败计数
|
||||
_failureCounts.TryRemove(channelKey, out _);
|
||||
|
||||
Reference in New Issue
Block a user