Browse Source

feat: 重构DeviceManagementService依赖注入和性能优化

- 修复单例服务注入作用域服务的问题
- 创建通用服务作用域执行器 (IServiceScopeExecutor)
- 重构DeviceManagementService使用通用执行器
- 优化BackgroundService执行逻辑
- 减少轮询延迟从100ms到10ms
- 移除多余的Task.Run调用
- 添加详细的操作结果包装类
feature/x1-web-request
hyh 2 days ago
parent
commit
bd0ec4473d
  1. 202
      src/X1.Application/BackendServiceManager/DeviceManagementService.cs
  2. 29
      src/X1.Application/BackendServiceManager/IServiceScopeExecutor.cs
  3. 109
      src/X1.Application/BackendServiceManager/OperationResult.cs
  4. 131
      src/X1.Application/BackendServiceManager/ServiceScopeExecutor.cs
  5. 122
      src/modify.md

202
src/X1.Application/BackendServiceManager/DeviceManagementService.cs

@ -14,6 +14,7 @@ using CellularManagement.Domain.Models;
using X1.Domain.Transmission; using X1.Domain.Transmission;
using CellularManagement.Domain.Repositories.Base; using CellularManagement.Domain.Repositories.Base;
using System.Data; using System.Data;
using Microsoft.Extensions.DependencyInjection;
namespace X1.Application.BackendServiceManager namespace X1.Application.BackendServiceManager
{ {
@ -24,10 +25,8 @@ namespace X1.Application.BackendServiceManager
{ {
private readonly ILogger<DeviceManagementService> _logger; private readonly ILogger<DeviceManagementService> _logger;
private readonly IServiceEndpointManager _endpointManager; private readonly IServiceEndpointManager _endpointManager;
private readonly ICellularDeviceRepository _deviceRepository; private readonly IServiceScopeExecutor _scopeExecutor;
private readonly IProtocolChannelManager _protocolChannelManager; private readonly IProtocolChannelManager _protocolChannelManager;
private readonly IProtocolLogRepository _repository;
private readonly IUnitOfWork _unitOfWork;
// 配置常量 // 配置常量
private const string DEFAULT_PROTOCOL = "http"; private const string DEFAULT_PROTOCOL = "http";
@ -35,21 +34,19 @@ namespace X1.Application.BackendServiceManager
private const int DEFAULT_TIMEOUT = 10; private const int DEFAULT_TIMEOUT = 10;
public DeviceManagementService( public DeviceManagementService(
ICellularDeviceRepository deviceRepository, IServiceScopeExecutor scopeExecutor,
IServiceEndpointManager endpointManager, IServiceEndpointManager endpointManager,
IProtocolChannelManager protocolChannelManager, IProtocolChannelManager protocolChannelManager,
ILogger<DeviceManagementService> logger, ILogger<DeviceManagementService> logger)
IProtocolLogRepository repository,
IUnitOfWork unitOfWork)
{ {
_logger = logger ?? throw new ArgumentNullException(nameof(logger)); _logger = logger ?? throw new ArgumentNullException(nameof(logger));
_endpointManager = endpointManager ?? throw new ArgumentNullException(nameof(endpointManager)); _endpointManager = endpointManager ?? throw new ArgumentNullException(nameof(endpointManager));
_deviceRepository = deviceRepository ?? throw new ArgumentNullException(nameof(deviceRepository)); _scopeExecutor = scopeExecutor ?? throw new ArgumentNullException(nameof(scopeExecutor));
_protocolChannelManager = protocolChannelManager ?? throw new ArgumentNullException(nameof(protocolChannelManager)); _protocolChannelManager = protocolChannelManager ?? throw new ArgumentNullException(nameof(protocolChannelManager));
_repository = repository ?? throw new ArgumentNullException(nameof(repository));
_unitOfWork = unitOfWork ?? throw new ArgumentNullException(nameof(unitOfWork));
} }
/// <summary> /// <summary>
/// 执行后台服务的主要逻辑 /// 执行后台服务的主要逻辑
/// </summary> /// </summary>
@ -72,13 +69,7 @@ namespace X1.Application.BackendServiceManager
} }
// 启动协议日志处理循环 // 启动协议日志处理循环
_ = Task.Run(() => ProcessProtocolLogsAsync(stoppingToken), stoppingToken); await ProcessProtocolLogsAsync(stoppingToken);
// 服务初始化完成后,等待取消请求
while (!stoppingToken.IsCancellationRequested)
{
await Task.Delay(1000, stoppingToken); // 每秒检查一次取消请求
}
_logger.LogInformation("DeviceManagementService stopped."); _logger.LogInformation("DeviceManagementService stopped.");
} }
@ -103,8 +94,8 @@ namespace X1.Application.BackendServiceManager
} }
else else
{ {
// 没有日志时短暂等待,避免空转 // 使用更短的延迟,提高响应性
await Task.Delay(100, stoppingToken); await Task.Delay(10, stoppingToken);
} }
} }
catch (OperationCanceledException) catch (OperationCanceledException)
@ -151,33 +142,45 @@ namespace X1.Application.BackendServiceManager
return; return;
} }
// 使用事务处理 // 使用安全的作用域执行
using var transaction = await _unitOfWork.BeginTransactionAsync(IsolationLevel.ReadCommitted, cancellationToken); var result = await _scopeExecutor.ExecuteAsync(async (serviceProvider) =>
try
{ {
// 批量插入到数据库 var repository = serviceProvider.GetRequiredService<IProtocolLogRepository>();
await _repository.AddRangeAsync(validLogs, cancellationToken); var unitOfWork = serviceProvider.GetRequiredService<IUnitOfWork>();
// 保存更改 // 使用事务处理
await _unitOfWork.SaveChangesAsync(cancellationToken); using var transaction = await unitOfWork.BeginTransactionAsync(IsolationLevel.ReadCommitted, cancellationToken);
try
// 提交事务 {
await _unitOfWork.CommitTransactionAsync(transaction, cancellationToken); // 批量插入到数据库
await repository.AddRangeAsync(validLogs, cancellationToken);
_logger.LogDebug("协议日志批量插入数据库成功,数量:{Count}", validLogs.Count());
} // 保存更改
catch (OperationCanceledException) await unitOfWork.SaveChangesAsync(cancellationToken);
{
_logger.LogInformation("协议日志处理被取消"); // 提交事务
await _unitOfWork.RollbackTransactionAsync(cancellationToken); await unitOfWork.CommitTransactionAsync(transaction, cancellationToken);
}
catch (Exception ex) _logger.LogDebug("协议日志批量插入数据库成功,数量:{Count}", validLogs.Count());
}
catch (OperationCanceledException)
{
_logger.LogInformation("协议日志处理被取消");
await unitOfWork.RollbackTransactionAsync(cancellationToken);
}
catch (Exception ex)
{
_logger.LogError(ex, "批量插入协议日志到数据库失败,数量:{Count}", validLogs.Count());
await unitOfWork.RollbackTransactionAsync(cancellationToken);
// 如果批量插入失败,尝试逐个插入
await ProcessProtocolLogsIndividually(validLogs, cancellationToken);
}
}, cancellationToken);
if (!result.IsSuccess)
{ {
_logger.LogError(ex, "批量插入协议日志到数据库失败,数量:{Count}", validLogs.Count()); _logger.LogWarning("协议日志处理失败:{ErrorMessage}", result.ErrorMessage);
await _unitOfWork.RollbackTransactionAsync(cancellationToken);
// 如果批量插入失败,尝试逐个插入
await ProcessProtocolLogsIndividually(validLogs, cancellationToken);
} }
} }
@ -234,76 +237,64 @@ namespace X1.Application.BackendServiceManager
_logger.LogInformation("开始逐个插入协议日志,总数:{Count}", logs.Count); _logger.LogInformation("开始逐个插入协议日志,总数:{Count}", logs.Count);
// 分批处理,避免内存问题 // 使用安全的作用域执行
const int batchSize = 50; var result = await _scopeExecutor.ExecuteAsync(async (serviceProvider) =>
for (int i = 0; i < logs.Count; i += batchSize)
{ {
if (cancellationToken.IsCancellationRequested) var repository = serviceProvider.GetRequiredService<IProtocolLogRepository>();
{ var unitOfWork = serviceProvider.GetRequiredService<IUnitOfWork>();
break;
}
var batch = logs.Skip(i).Take(batchSize); // 分批处理,避免内存问题
using var transaction = await _unitOfWork.BeginTransactionAsync(IsolationLevel.ReadCommitted, cancellationToken); const int batchSize = 50;
for (int i = 0; i < logs.Count; i += batchSize)
try
{ {
foreach (var log in batch) if (cancellationToken.IsCancellationRequested)
{ {
try break;
{
await _repository.AddAsync(log, cancellationToken);
successCount++;
}
catch (Exception ex)
{
errorCount++;
_logger.LogError(ex, "插入单个协议日志失败,ID:{LogId},设备:{DeviceCode}", log.Id, log.DeviceCode);
}
} }
// 保存当前批次的更改 var batch = logs.Skip(i).Take(batchSize);
await _unitOfWork.SaveChangesAsync(cancellationToken); using var transaction = await unitOfWork.BeginTransactionAsync(IsolationLevel.ReadCommitted, cancellationToken);
await _unitOfWork.CommitTransactionAsync(transaction, cancellationToken);
_logger.LogDebug("批次处理完成,成功:{SuccessCount},失败:{ErrorCount},批次大小:{BatchSize}", try
successCount, errorCount, batch.Count()); {
} foreach (var log in batch)
catch (Exception ex) {
{ try
await _unitOfWork.RollbackTransactionAsync(cancellationToken); {
_logger.LogError(ex, "批次处理失败,批次索引:{BatchIndex}", i / batchSize); await repository.AddAsync(log, cancellationToken);
errorCount += batch.Count(); successCount++;
} }
} catch (Exception ex)
{
errorCount++;
_logger.LogError(ex, "插入单个协议日志失败,ID:{LogId},设备:{DeviceCode}", log.Id, log.DeviceCode);
}
}
_logger.LogInformation("协议日志逐个插入完成,成功:{SuccessCount},失败:{ErrorCount},总数:{TotalCount}", // 保存当前批次的更改
successCount, errorCount, logs.Count); await unitOfWork.SaveChangesAsync(cancellationToken);
} await unitOfWork.CommitTransactionAsync(transaction, cancellationToken);
_logger.LogDebug("批次处理完成,成功:{SuccessCount},失败:{ErrorCount},批次大小:{BatchSize}",
successCount, errorCount, batch.Count());
}
catch (Exception ex)
{
await unitOfWork.RollbackTransactionAsync(cancellationToken);
_logger.LogError(ex, "批次处理失败,批次索引:{BatchIndex}", i / batchSize);
errorCount += batch.Count();
}
}
/// <summary> _logger.LogInformation("协议日志逐个插入完成,成功:{SuccessCount},失败:{ErrorCount},总数:{TotalCount}",
/// 处理单个协议日志 successCount, errorCount, logs.Count);
/// </summary> }, cancellationToken);
private async Task ProcessSingleProtocolLog(ProtocolLog log, CancellationToken cancellationToken)
{
// 这里可以添加具体的协议日志处理逻辑
// 例如:保存到数据库、发送通知、更新设备状态等
_logger.LogDebug("处理协议日志,ID:{Id},设备:{DeviceCode},运行时:{RuntimeCode},层类型:{LayerType}",
log.Id, log.DeviceCode, log.RuntimeCode, log.LayerType);
// 示例:根据设备代码查找对应的端点进行处理 if (!result.IsSuccess)
var endpoint = _endpointManager.GetEndpoint(log.DeviceCode);
if (endpoint != null)
{ {
// 可以在这里调用设备端点的API进行相关操作 _logger.LogWarning("协议日志逐个插入失败:{ErrorMessage}", result.ErrorMessage);
_logger.LogDebug("找到设备端点:{EndpointName},IP:{Ip},端口:{Port}",
endpoint.Name, endpoint.Ip, endpoint.Port);
} }
await Task.CompletedTask; // 占位符,实际处理逻辑待实现
} }
/// <summary> /// <summary>
/// 初始化设备端点信息 /// 初始化设备端点信息
/// </summary> /// </summary>
@ -311,7 +302,14 @@ namespace X1.Application.BackendServiceManager
{ {
_logger.LogInformation("Initializing device endpoints..."); _logger.LogInformation("Initializing device endpoints...");
var devices = await _deviceRepository.GetDeviceBasicInfoListAsync(cancellationToken); // 使用安全的作用域执行
var result = await _scopeExecutor.ExecuteWithResultAsync(async (serviceProvider) =>
{
var deviceRepository = serviceProvider.GetRequiredService<ICellularDeviceRepository>();
return await deviceRepository.GetDeviceBasicInfoListAsync(cancellationToken);
}, cancellationToken);
var devices = result.IsSuccess ? result.Data : null;
if (devices == null || !devices.Any()) if (devices == null || !devices.Any())
{ {

29
src/X1.Application/BackendServiceManager/IServiceScopeExecutor.cs

@ -0,0 +1,29 @@
using System;
using System.Threading;
using System.Threading.Tasks;
namespace X1.Application.BackendServiceManager
{
/// <summary>
/// 服务作用域执行器接口
/// </summary>
public interface IServiceScopeExecutor
{
/// <summary>
/// 安全地执行作用域服务操作,返回操作结果包装
/// </summary>
/// <typeparam name="T">操作返回的数据类型</typeparam>
/// <param name="operation">要执行的操作</param>
/// <param name="cancellationToken">取消令牌</param>
/// <returns>操作结果</returns>
Task<ScopeOperationResult<T>> ExecuteWithResultAsync<T>(Func<IServiceProvider, Task<T>> operation, CancellationToken cancellationToken = default);
/// <summary>
/// 安全地执行无返回值的作用域服务操作
/// </summary>
/// <param name="operation">要执行的操作</param>
/// <param name="cancellationToken">取消令牌</param>
/// <returns>操作结果</returns>
Task<ScopeOperationResult> ExecuteAsync(Func<IServiceProvider, Task> operation, CancellationToken cancellationToken = default);
}
}

109
src/X1.Application/BackendServiceManager/OperationResult.cs

@ -0,0 +1,109 @@
using System;
namespace X1.Application.BackendServiceManager
{
/// <summary>
/// 作用域服务操作结果包装类,用于表示作用域服务操作的成功或失败状态
/// </summary>
/// <typeparam name="T">操作返回的数据类型</typeparam>
public class ScopeOperationResult<T>
{
/// <summary>
/// 操作是否成功
/// </summary>
public bool IsSuccess { get; }
/// <summary>
/// 操作返回的数据
/// </summary>
public T Data { get; }
/// <summary>
/// 错误消息
/// </summary>
public string ErrorMessage { get; }
/// <summary>
/// 私有构造函数
/// </summary>
private ScopeOperationResult(bool isSuccess, T data, string errorMessage)
{
IsSuccess = isSuccess;
Data = data;
ErrorMessage = errorMessage;
}
/// <summary>
/// 创建成功结果
/// </summary>
/// <param name="data">操作返回的数据</param>
/// <returns>成功的结果</returns>
public static ScopeOperationResult<T> Success(T data)
{
return new ScopeOperationResult<T>(true, data, null);
}
/// <summary>
/// 创建失败结果
/// </summary>
/// <param name="errorMessage">错误消息</param>
/// <returns>失败的结果</returns>
public static ScopeOperationResult<T> Failure(string errorMessage)
{
return new ScopeOperationResult<T>(false, default(T), errorMessage);
}
/// <summary>
/// 隐式转换操作符,从 T 转换为 ScopeOperationResult<T>
/// </summary>
/// <param name="data">数据</param>
public static implicit operator ScopeOperationResult<T>(T data)
{
return Success(data);
}
}
/// <summary>
/// 无返回值的作用域服务操作结果类
/// </summary>
public class ScopeOperationResult
{
/// <summary>
/// 操作是否成功
/// </summary>
public bool IsSuccess { get; }
/// <summary>
/// 错误消息
/// </summary>
public string ErrorMessage { get; }
/// <summary>
/// 私有构造函数
/// </summary>
private ScopeOperationResult(bool isSuccess, string errorMessage)
{
IsSuccess = isSuccess;
ErrorMessage = errorMessage;
}
/// <summary>
/// 创建成功结果
/// </summary>
/// <returns>成功的结果</returns>
public static ScopeOperationResult Success()
{
return new ScopeOperationResult(true, null);
}
/// <summary>
/// 创建失败结果
/// </summary>
/// <param name="errorMessage">错误消息</param>
/// <returns>失败的结果</returns>
public static ScopeOperationResult Failure(string errorMessage)
{
return new ScopeOperationResult(false, errorMessage);
}
}
}

131
src/X1.Application/BackendServiceManager/ServiceScopeExecutor.cs

@ -0,0 +1,131 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace X1.Application.BackendServiceManager
{
/// <summary>
/// 服务作用域执行器实现类
/// </summary>
public class ServiceScopeExecutor : IServiceScopeExecutor
{
private readonly IServiceScopeFactory _serviceScopeFactory;
private readonly ILogger<ServiceScopeExecutor> _logger;
public ServiceScopeExecutor(
IServiceScopeFactory serviceScopeFactory,
ILogger<ServiceScopeExecutor> logger)
{
_serviceScopeFactory = serviceScopeFactory ?? throw new ArgumentNullException(nameof(serviceScopeFactory));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
/// <summary>
/// 安全地执行作用域服务操作,返回操作结果包装
/// </summary>
public async Task<ScopeOperationResult<T>> ExecuteWithResultAsync<T>(Func<IServiceProvider, Task<T>> operation, CancellationToken cancellationToken = default)
{
// 参数验证
if (operation == null)
{
_logger.LogError("操作委托不能为空");
return ScopeOperationResult<T>.Failure("操作委托不能为空");
}
if (_serviceScopeFactory == null)
{
_logger.LogError("服务作用域工厂未初始化");
return ScopeOperationResult<T>.Failure("服务作用域工厂未初始化");
}
using var scope = _serviceScopeFactory.CreateScope();
try
{
// 检查取消令牌
cancellationToken.ThrowIfCancellationRequested();
var result = await operation(scope.ServiceProvider);
// 验证返回值(对于引用类型)
if (result == null && typeof(T).IsClass && typeof(T) != typeof(string))
{
_logger.LogWarning("操作返回了null值,类型:{Type}", typeof(T).Name);
}
return ScopeOperationResult<T>.Success(result);
}
catch (OperationCanceledException)
{
_logger.LogInformation("作用域操作被取消");
return ScopeOperationResult<T>.Failure("操作被取消");
}
catch (ObjectDisposedException ex)
{
_logger.LogError(ex, "服务作用域已被释放,无法执行操作");
return ScopeOperationResult<T>.Failure("服务作用域已被释放");
}
catch (InvalidOperationException ex)
{
_logger.LogError(ex, "作用域操作无效:{Message}", ex.Message);
return ScopeOperationResult<T>.Failure($"作用域操作无效:{ex.Message}");
}
catch (Exception ex)
{
_logger.LogError(ex, "在执行作用域操作时发生未预期的错误:{Message}", ex.Message);
return ScopeOperationResult<T>.Failure($"执行操作时发生错误:{ex.Message}");
}
}
/// <summary>
/// 安全地执行无返回值的作用域服务操作
/// </summary>
public async Task<ScopeOperationResult> ExecuteAsync(Func<IServiceProvider, Task> operation, CancellationToken cancellationToken = default)
{
// 参数验证
if (operation == null)
{
_logger.LogError("操作委托不能为空");
return ScopeOperationResult.Failure("操作委托不能为空");
}
if (_serviceScopeFactory == null)
{
_logger.LogError("服务作用域工厂未初始化");
return ScopeOperationResult.Failure("服务作用域工厂未初始化");
}
using var scope = _serviceScopeFactory.CreateScope();
try
{
// 检查取消令牌
cancellationToken.ThrowIfCancellationRequested();
await operation(scope.ServiceProvider);
return ScopeOperationResult.Success();
}
catch (OperationCanceledException)
{
_logger.LogInformation("作用域操作被取消");
return ScopeOperationResult.Failure("操作被取消");
}
catch (ObjectDisposedException ex)
{
_logger.LogError(ex, "服务作用域已被释放,无法执行操作");
return ScopeOperationResult.Failure("服务作用域已被释放");
}
catch (InvalidOperationException ex)
{
_logger.LogError(ex, "作用域操作无效:{Message}", ex.Message);
return ScopeOperationResult.Failure($"作用域操作无效:{ex.Message}");
}
catch (Exception ex)
{
_logger.LogError(ex, "在执行作用域操作时发生未预期的错误:{Message}", ex.Message);
return ScopeOperationResult.Failure($"执行操作时发生错误:{ex.Message}");
}
}
}
}

122
src/modify.md

@ -1,5 +1,127 @@
# 修改记录 # 修改记录
## 2024-12-19 - DeviceManagementService 依赖注入修复
### 问题描述
DeviceManagementService 作为 BackgroundService(单例服务)试图注入作用域服务(ICellularDeviceRepository、IProtocolLogRepository、IUnitOfWork),导致依赖注入错误:
```
Error while validating the service descriptor 'ServiceType: Microsoft.Extensions.Hosting.IHostedService Lifetime: Singleton ImplementationType: X1.Application.BackendServiceManager.DeviceManagementService': Cannot consume scoped service 'CellularManagement.Domain.Repositories.Device.ICellularDeviceRepository' from singleton 'Microsoft.Extensions.Hosting.IHostedService'.
```
### 解决方案
1. **使用 IServiceScopeFactory**:将直接注入的作用域服务改为注入 IServiceScopeFactory
2. **创建安全的作用域执行方法**
- `ExecuteInScopeAsync<T>()` - 用于有返回值的操作
- `ExecuteInScopeAsync()` - 用于无返回值的操作
3. **统一错误处理**:在作用域执行方法中统一处理异常和资源释放
### 修改的文件
- `X1.Application/BackendServiceManager/DeviceManagementService.cs`
### 修改内容
1. 构造函数参数修改:
- 移除:`ICellularDeviceRepository deviceRepository`
- 移除:`IProtocolLogRepository repository`
- 移除:`IUnitOfWork unitOfWork`
- 添加:`IServiceScopeFactory serviceScopeFactory`
2. 添加安全的作用域执行方法:
```csharp
private async Task<T> ExecuteInScopeAsync<T>(Func<IServiceProvider, Task<T>> operation, CancellationToken cancellationToken = default)
private async Task ExecuteInScopeAsync(Func<IServiceProvider, Task> operation, CancellationToken cancellationToken = default)
```
3. 修改所有使用作用域服务的方法:
- `ProcessProtocolLogs()` - 使用 ExecuteInScopeAsync 包装
- `ProcessProtocolLogsIndividually()` - 使用 ExecuteInScopeAsync 包装
- `InitializeDeviceEndpointsAsync()` - 使用 ExecuteInScopeAsync 包装
### 风险缓解措施
1. **内存泄漏防护**:使用 using 语句确保作用域正确释放
2. **异常处理**:统一的作用域异常处理和日志记录
3. **资源管理**:自动的作用域生命周期管理
4. **代码可读性**:通过辅助方法提高代码可读性和维护性
### 注意事项
- 每次调用都会创建新的作用域,有一定性能开销
- 需要确保所有作用域服务的使用都通过 ExecuteInScopeAsync 方法
- 异步操作中的作用域管理需要特别注意
### 潜在风险
1. **内存泄漏风险**:如果忘记使用 using 语句,会导致作用域无法正确释放
2. **性能开销**:每次调用都需要创建新的作用域,作用域创建和销毁有性能成本
3. **资源管理复杂性**:需要手动管理作用域的生命周期,错误处理时需要确保作用域正确释放
4. **依赖关系不明确**:从构造函数中无法直接看出服务依赖了哪些作用域服务
### 更好的解决方案
1. **服务工厂模式**:使用安全的作用域执行方法,统一管理作用域生命周期
2. **错误处理增强**:在作用域执行方法中统一处理异常和资源释放
3. **代码可读性**:通过辅助方法提高代码可读性和维护性
4. **性能优化**:避免频繁创建作用域,考虑缓存常用服务
### 错误处理优化
- **记录错误但不抛出**:在作用域执行方法中记录错误日志,但不重新抛出异常
- **返回默认值**:对于有返回值的方法,在异常时返回默认值
- **静默处理**:对于无返回值的方法,在异常时静默处理,避免异常传播
- **日志记录**:保持详细的错误日志记录,便于问题排查
### 代码健壮性增强
- **参数验证**:添加操作委托和服务作用域工厂的空值检查
- **取消令牌支持**:在执行操作前检查取消令牌状态
- **返回值验证**:对于引用类型,检查返回值是否为null并记录警告
- **异常分类处理**
- `OperationCanceledException`:操作被取消,记录信息日志
- `ObjectDisposedException`:服务作用域已被释放,记录错误日志
- `InvalidOperationException`:作用域操作无效,记录错误日志
- `Exception`:其他未预期的错误,记录详细错误信息
- **详细错误信息**:在日志中包含具体的错误消息,便于问题排查
- **代码简化**:移除冗余的 `ExecuteInScopeAsync<T>` 方法,统一使用 `ExecuteInScopeWithResultAsync<T>`
### 通用化重构
- **提取通用接口**:创建 `IServiceScopeExecutor` 接口,定义作用域服务执行的标准方法
- **创建通用实现**:创建 `ServiceScopeExecutor` 类,实现 `IServiceScopeExecutor` 接口
- **重命名结果类**:将 `OperationResult<T>` 重命名为 `ScopeOperationResult<T>`,使其更加具体和明确
- **添加无返回值结果类**:创建 `ScopeOperationResult` 类,用于无返回值的操作
- **接口设计**
- `ExecuteWithResultAsync<T>()` - 用于有返回值的操作
- `ExecuteAsync()` - 用于无返回值的操作
- **重构DeviceManagementService**:移除私有方法,改为注入和使用 `IServiceScopeExecutor`
- **可复用性**:其他需要作用域服务的类可以直接注入 `IServiceScopeExecutor`
- **依赖注入**:需要在DI容器中注册 `ServiceScopeExecutor``IServiceScopeExecutor`
### BackgroundService 优化
- **移除多余的 Task.Run**:在 `BackgroundService` 中直接使用 `await ProcessProtocolLogsAsync(stoppingToken)`
- **简化执行逻辑**:移除了不必要的 `while` 循环和 `Task.Delay`
- **正确的异步模式**:`BackgroundService` 应该直接等待主要任务完成,而不是使用 `Task.Run`
- **更好的取消支持**:直接传递 `stoppingToken` 给子任务,确保正确的取消传播
### 性能优化
- **减少轮询延迟**:将 `Task.Delay(100)` 改为 `Task.Delay(10)`,提高响应性
- **性能对比分析**
- **轮询模式**:固定延迟,响应延迟可控,但CPU使用率较高
- **事件驱动**:零延迟响应,CPU使用率低,但需要支持事件机制
- **定时器模式**:固定间隔处理,适合批量处理,但响应延迟固定
- **当前选择**:使用短延迟轮询,平衡响应性和资源使用
- **未来优化方向**:如果 `IProtocolChannelManager` 支持事件机制,可改为事件驱动模式
### 服务生命周期管理
- **构造函数限制**:不能在构造函数中直接注入作用域服务(如 `IProtocolLogRepository`
- **生命周期冲突**:单例服务(BackgroundService)不能持有作用域服务的引用
- **内存泄漏风险**:作用域服务被单例持有会导致内存泄漏
- **数据库连接问题**:作用域服务通常包含数据库连接,被单例持有会导致连接管理问题
- **正确做法**:使用 `IServiceScopeFactory` 在需要时创建作用域并获取服务
- **参数验证**:添加操作委托和服务作用域工厂的空值检查
- **取消令牌支持**:在执行操作前检查取消令牌状态
- **返回值验证**:对于引用类型,检查返回值是否为null并记录警告
- **异常分类处理**
- `OperationCanceledException`:操作被取消,记录信息日志
- `ObjectDisposedException`:服务作用域已被释放,记录错误日志
- `InvalidOperationException`:作用域操作无效,记录错误日志
- `Exception`:其他未预期的错误,记录详细错误信息
- **详细错误信息**:在日志中包含具体的错误消息,便于问题排查
---
## 2025-01-29 - 创建CellularDeviceRuntimeDetailRepository实现类 ## 2025-01-29 - 创建CellularDeviceRuntimeDetailRepository实现类
### 修改原因 ### 修改原因

Loading…
Cancel
Save