From ffb22e1f2027bd434b4115c3a2c1a9ba88551a4a Mon Sep 17 00:00:00 2001 From: hsc Date: Fri, 12 Jun 2026 09:25:40 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AE=BE=E5=A4=87=E7=BC=96=E8=BE=911?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ViewModels/ParametersManagerViewModel.cs | 38 +++++---- TestingModule/Views/ParametersManager.xaml | 9 +- UIShare/GlobalVariable/DeviceManager.cs | 83 ++++++++++++++++++- 3 files changed, 111 insertions(+), 19 deletions(-) diff --git a/TestingModule/ViewModels/ParametersManagerViewModel.cs b/TestingModule/ViewModels/ParametersManagerViewModel.cs index dbb14ba..8350c3a 100644 --- a/TestingModule/ViewModels/ParametersManagerViewModel.cs +++ b/TestingModule/ViewModels/ParametersManagerViewModel.cs @@ -67,29 +67,44 @@ namespace TestingModule.ViewModels private ScopedContext _ScopedContext { get; set; } private readonly SystemConfig _systemConfig; private readonly GlobalInfo _globalInfo; + private readonly DeviceManager _deviceManager; #region 命令 public ICommand ParameterAddCommand { get; set; } public ICommand ParameterEditCommand { get; set; } public ICommand ParameterDeleteCommand { get; set; } public ICommand DeviceEditCommand { get; set; } - public ICommand ReconnnectCommand { get; set; } + public ICommand ReConnectCommand { get; set; } public ICommand CloseCommand { get; set; } + public ICommand LoadedCommand { get; set; } #endregion - public ParametersManagerViewModel(IContainerProvider containerProvider, ScopedContext scopedContext, SystemConfig systemConfig, GlobalInfo globalInfo) : base(containerProvider) + public ParametersManagerViewModel(IContainerProvider containerProvider) : base(containerProvider) { - _ScopedContext = scopedContext; - _systemConfig = systemConfig; - _globalInfo = globalInfo; + + _ScopedContext = containerProvider.Resolve(); + _systemConfig = containerProvider.Resolve(); + _deviceManager = containerProvider.Resolve(); + _globalInfo = containerProvider.Resolve(); Program = _ScopedContext.Program; ParameterAddCommand = new DelegateCommand(ParameterAdd); ParameterEditCommand = new DelegateCommand(ParameterEdit); ParameterDeleteCommand = new DelegateCommand(ParameterDelete); DeviceEditCommand = new DelegateCommand(DeviceEdit); + ReConnectCommand = new AsyncDelegateCommand(OnReConnect); + CloseCommand = new AsyncDelegateCommand(OnClose); + LoadedCommand = new DelegateCommand(OnLoad); } - #region 委托命令 - + private void OnLoad() + { + DeviceInfoVM = _systemConfig.DeviceList; + } private async Task OnReConnect() + { + await _deviceManager.ConnectSpecifiedDevice(SelectedDevice.DeviceName); + } private async Task OnClose() + { + await _deviceManager.CloseDeviceAsync(SelectedDevice.DeviceName); + } private void DeviceEdit() { if (!_globalInfo.IsAdmin) return; @@ -98,14 +113,7 @@ namespace TestingModule.ViewModels return; } var type = SelectedDevice.DeviceType.Split('.').Last(); - if(type=="E36233A"|| type == "IT6724CReverse") - { - _dialogService.Show("Backfeed"); - } - else - { - _dialogService.Show(type); - } + _dialogService.Show(type); } private void ParameterDelete() diff --git a/TestingModule/Views/ParametersManager.xaml b/TestingModule/Views/ParametersManager.xaml index 3f257d7..6861240 100644 --- a/TestingModule/Views/ParametersManager.xaml +++ b/TestingModule/Views/ParametersManager.xaml @@ -3,6 +3,7 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:i="http://schemas.microsoft.com/xaml/behaviors" xmlns:prism="http://prismlibrary.com/" xmlns:converters="clr-namespace:UIShare.Converters;assembly=UIShare" xmlns:sys="clr-namespace:System;assembly=mscorlib" @@ -18,7 +19,11 @@ - + + + + + @@ -123,7 +128,7 @@ + Command="{Binding ReConnectCommand}" /> diff --git a/UIShare/GlobalVariable/DeviceManager.cs b/UIShare/GlobalVariable/DeviceManager.cs index 3fa58e5..7eaaf67 100644 --- a/UIShare/GlobalVariable/DeviceManager.cs +++ b/UIShare/GlobalVariable/DeviceManager.cs @@ -17,6 +17,7 @@ namespace UIShare.GlobalVariable /// public class DeviceManager { + private object _lockObj = new object(); public SystemConfig _systemConfig { get; set; } /// 按 DeviceName 索引的设备字典,便于业务层按名取实例。 @@ -115,7 +116,86 @@ namespace UIShare.GlobalVariable await ConnectInternalAsync(info, device, ct); } - + /// + /// 异步关闭指定设备,释放底层连接并更新 UI 状态 + /// + public async Task CloseDeviceAsync(string deviceName) + { + if (string.IsNullOrWhiteSpace(deviceName)) return; + + IBaseInterface? device; + DeviceInfoVM? info; + + lock (_lockObj) + { + if (!DeviceMap.TryGetValue(deviceName, out device)) return; + + info = _systemConfig?.DeviceList? + .FirstOrDefault(d => d != null && string.Equals(d.DeviceName, deviceName, StringComparison.OrdinalIgnoreCase)); + } + + await CloseInternalAsync(info, device); + } + + /// + /// 异步关闭所有设备 + /// + public async Task CloseAllDevicesAsync() + { + List tasks = new List(); + + lock (_lockObj) + { + if (DeviceMap.Count == 0) return; + + foreach (var kvp in DeviceMap) + { + string deviceName = kvp.Key; + var device = kvp.Value; + var info = _systemConfig?.DeviceList? + .FirstOrDefault(d => d != null && string.Equals(d.DeviceName, deviceName, StringComparison.OrdinalIgnoreCase)); + + tasks.Add(CloseInternalAsync(info, device)); + } + } + + await Task.WhenAll(tasks); + LoggerHelper.Info("所有设备已执行关闭操作。"); + } + + #region 辅助方法 + private async Task CloseInternalAsync(DeviceInfoVM? info, IBaseInterface device) + { + string name = info?.DeviceName ?? device.GetType().Name; + string conn = info?.ConnectionType ?? "?"; + + try + { + // 如果设备本身已经是断开状态,直接更新 UI 并返回 + if (!device.IsConnected) + { + if (info != null) info.IsConnected = false; + LoggerHelper.Info($"设备 [{name}] 本就处于断开状态。"); + return; + } + await Task.Run(() => device.Close()); + + LoggerHelper.Info($"设备 [{name}/{conn}] 已成功关闭连接。"); + } + catch (Exception ex) + { + var inner = ex.InnerException?.Message ?? ex.Message; + LoggerHelper.Error($"设备 [{name}/{conn}] 关闭连接时出现异常: {inner}"); + } + finally + { + // 无论关闭时是否抛出异常,均强制同步 UI 状态为未连接 + if (info != null) + { + info.IsConnected = false; + } + } + } private async Task ConnectInternalAsync(DeviceInfoVM? info, IBaseInterface device, CancellationToken ct) { string name = info?.DeviceName ?? device.GetType().Name; @@ -176,7 +256,6 @@ namespace UIShare.GlobalVariable } return await sp.ConnectAsync(ct); } - #region 辅助方法 private static IReadOnlyDictionary BuildDeviceTypeMap() { try