You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 01:36:03