WPF集成DNP3 Nuget包时RunChannel方法CPU占用过高解决方案求助
问题根因
空while(true)循环没有任何阻塞或等待逻辑,会持续占用CPU时间片全速执行,是导致CPU占用过高的直接原因。你需要保留RunChannel方法不退出以维持dnp3运行环境不被释放,同时避免无效的空转即可解决问题。
优化方案
将空死循环替换为基于取消令牌的异步等待逻辑,既可以实现保活效果、不占用CPU资源,还可以在程序退出时可控释放资源:
1. 修改RunChannel方法
添加取消令牌参数,用无限异步等待替换空循环:
public static async Task RunChannel(MasterChannel channel, CancellationToken cancellationToken) { // ANCHOR: association_create var association = channel.AddAssociation( 1024, GetAssociationConfig(), new TestReadHandler(), new TestAssocationHandler() ); // ANCHOR_END: association_create // ANCHOR: add_poll var poll = channel.AddPoll(association, Request.ClassRequest(false, true, true, true), TimeSpan.FromSeconds(5)); // ANCHOR_END: add_poll // start communications channel.Enable(); // 等待取消信号,无CPU占用 await Task.Delay(Timeout.Infinite, cancellationToken); }
2. 修改MainWindow逻辑
添加取消令牌源管理生命周期,窗口关闭时主动取消任务释放资源:
public partial class MainWindow : Window { // 声明dnp3服务的取消令牌源 private readonly CancellationTokenSource _dnp3Cts = new CancellationTokenSource(); public MainWindow() { InitializeComponent(); // ANCHOR: logging_init // Initialize logging with the default configuration // This may only be called once during program initialization Logging.Configure( new LoggingConfig(), new Protocolo.ConsoleLogger() ); // ANCHOR_END: logging_init // ANCHOR: runtime_init var runtime = new Runtime(new RuntimeConfig { NumCoreThreads = 4 }); // ANCHOR_END: runtime_init // ANCHOR: create_master_channel var channel = MasterChannel.CreateTcpChannel( runtime, LinkErrorMode.Close, Protocolo.GetMasterChannelConfig(), new EndpointList("127.0.0.1:20000"), new ConnectStrategy(), new Protocolo.TestListener() ); // ANCHOR_END: create_master_channel Task.Run(async () => { try { // 传入取消令牌 await Protocolo.RunChannel(channel, _dnp3Cts.Token); } catch (OperationCanceledException) { // 程序退出触发的取消属于预期操作,无需额外处理异常 } finally { // ANCHOR: runtime_shutdown runtime.Shutdown(); // ANCHOR_END: runtime_shutdown } }); } // 窗口关闭时触发取消,正常释放资源 protected override void OnClosing(CancelEventArgs e) { _dnp3Cts.Cancel(); base.OnClosing(e); } }
3. 日志输出调整
如果需要在Visual Studio的输出窗口查看日志,直接将ConsoleLogger类中的输出方法替换为Debug输出即可:
class ConsoleLogger : ILogger { public void OnMessage(LogLevel level, string message) { Debug.Write($"{message}"); } }
内容的提问来源于stack exchange,提问作者Ivan Raul Sanchez Diaz
相关产品推荐
相关产品推荐

