基于EasyModbusTCP的PLC数据拉取服务MVVM集成咨询
WPF MVVM模式下集成异步Modbus服务的问题
我是编程新手,仅学习编程数月,已使用EasyModbusTCP库开发出可正常运行的WPF程序,且实现了Modbus异步读取以避免界面冻结。现需扩展该程序,从Modbus拉取600余个线圈和寄存器的数据,同时借助CommunityToolkit迁移至MVVM模式,但不清楚如何在ViewModel中创建相关服务,对此感到困惑。以下为简化后的相关代码示例:
ConductivityView XAML代码
<ItemsControl Grid.Row="2" ItemsSource="{Binding ConductivityTanks}"> <ItemsControl.ItemTemplate> <DataTemplate DataType="{x:Type vm:ConductivityGridElementViewModel}"> <controls:ConductivityGridElement DataContext="{Binding}"></controls:ConductivityGridElement> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl>
CodeBehind代码
public partial class BConductivityView : UserControl { ConductivityViewModel conductivityViewModel; public BConductivityView() { InitializeComponent(); conductivityViewModel = new ConductivityViewModel(); this.DataContext = conductivityViewModel; } }
需要集成Modbus服务的ConductivityViewModel代码
public partial class ConductivityViewModel : ObservableObject { [ObservableProperty] private ObservableCollection<ConductivityGridElementViewModel> _conductivityTanks; public ConductivityViewModel() { _conductivityTanks = new ObservableCollection<ConductivityGridElementViewModel>(); ConductivityTanks.Clear(); //添加初始模拟数据用于显示 for (int i = 0; i <= 32; i++) { ConductivityTanks.Add(new ConductivityGridElementViewModel { Id = i.ToString(), Use = true, TankNo = i.ToString(), Sp = (1000 + i).ToString(), Pv = (1500 + i).ToString(), Valve = false, TimeLeft = (4 + i).ToString(), Timer = (5).ToString(), SensorMinimum = "0", SensorMaximum = "10000", Raw = "1670" }); } public void ModbusReadAsync() { // 发起异步调用启动Modbus拉取,并更新ConductivityTanks中的所有ConductivityGridElement } } }
当前的Modbus服务类代码
public static class ModbusService { public static CancellationTokenSource cts = new CancellationTokenSource(); public static ModbusClient MB = new ModbusClient(); private static bool[] coils1 = new bool[120]; private static bool[] coils2 = new bool[40]; private static int[] registers1 = new int[121]; private static int[] registers2 = new int[121]; private static int[] registers3 = new int[121]; public static void ConnectToPLC(string IP, int Port, bool ReConnect) { cts.Cancel(); ConnectionExist = false; MB.Disconnect(); MB = new ModbusClient(IP, Port); try { MB.Connect(); ConnectionExist = true; ReadPLCAsync(); } catch (Exception) { MessageBox.Show("连接错误。\n不读取PLC直接启动。"); } } public static async void ReadPLCAsync() { await Task.Run(async () => { await Read(cts.Token); }); } private static async Task<bool> Read(CancellationToken cancellationToken) { while (ConnectionExist) { try { coils1 = MB.ReadCoils(0, 120); coils2 = MB.ReadCoils(121, 40); registers1 = MB.ReadHoldingRegisters(0, 122); registers2 = MB.ReadHoldingRegisters(122, 122); registers3 = MB.ReadHoldingRegisters(244, 122); General.CPUinRUN = coils1[0]; General.ValveON = coils1[1]; General.SDCardEject = coils1[2]; General.SDCardEject = coils1[3]; Conductivity.MasterON = coils1[4]; Fresh.MasterON = coils1[5]; Level.MasterON = coils1[6]; General.SendEmail = coils1[7]; Array.Copy(coils1, 8, Conductivity.Valve, 0, 32); Array.Copy(coils1, 40, Conductivity.CValveMan, 0, 32); Array.Copy(coils1, 72, Fresh.FValve, 0, 32); Fresh.RunOnSaturday = coils1[104]; Fresh.RunOnSunday = coils1[105]; Fresh.RunOnWeekend = coils1[106]; Array.Copy(coils1, 107, Level.L_Alarm, 0, 10); Array.Copy(coils1, 117, Level.L_AlarmOFF, 0, 5); Array.Copy(coils2, 0, Level.L_AlarmOFF, 5, 5); Array.Copy(coils2, 5, Level.L_Filling, 0, 10); Array.Copy(coils2, 15, Level.L_InRange, 0, 10); Array.Copy(coils2, 25, Level.L_Valve, 0, 10); Conductivity.ON = coils2[35]; Fresh.ON = coils2[36]; Level.ON = coils2[37]; } catch (ConnectionException) { ConnectionExist = false; MBC.MB.Disconnect(); MessageBox.Show("从MBC类读取PLC时出现问题。"); } await Task.Delay(1000); } return true; } }
应用程序整体界面

内容的提问来源于stack exchange,提问作者Evgeniy
相关产品推荐
相关产品推荐

