Home > Software engineering >  performance issues with WPF
performance issues with WPF

Time:10-05

I am working with a dnp3 nuget package and I want to implement it in a WPF, and I achieve it by referring to this example Example

but I created another much simpler project to do the demonstration here on github , in my project create a class called protocol and paste all the master example eliminating the main function and changing the private functions for public functions, then inside my MainWindow.xaml.cs start the code

    {
        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(() => 
                {
                    try
                    {
                        Protocolo.RunChannel(channel).GetAwaiter().GetResult();
                    }
                    finally
                    {
                        // ANCHOR: runtime_shutdown
                        runtime.Shutdown();
                        // ANCHOR_END: runtime_shutdown
                    }
            }
            );

        }
    } 

I did performance profiles and RunChannel is what they demand a lot from the CPU

        public static async Task RunChannel(MasterChannel channel)
        {
            // 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();

            while (true)
            {
              //Here there was a switch that read the commands that were entered into the console but it is unnecessary, with the empty while it continues to update

            }
        }

I don't know why but without the While the received messages are not updated, (these messages arrive in the Logger) I have to keep this function always alive but I don't know how to do it without consuming so much CPU

to see the messages in the output you have to change Console.WriteLine to Debug.WriteLine

   class ConsoleLogger : ILogger
    {
        public void OnMessage(LogLevel level, string message)
        {
            Console.Write($"{message}");
            //this is inside the master example in the github link
        }
    }

CodePudding user response:

As commented before (answering about "performance issue"):

  1. Your empty while loop running without any pause or job. You need to fill loop with some job or simple pause (Thread.Sleep(10)/await Task.Delay(10)).
  2. Your RunChannel method have no any await, so you should get CS1998 warning "This async method lacks 'await'" and, obviously, put it into your while loop.

On DNP3 Github example, there is await GetInputAsync() inside while loop, which waits for user input with Console.ReadLine() and returns inputed string into switch statement.

So:

public MainWindow()
{
    // InitializeComponent() and other stuff...

    Task.Run(async () => // Make it async
    {
        try
        {
            // You really didn't want GetAwaiter().GetResult().
            await Protocolo.RunChannel(channel);
        }
        finally
        {
            runtime.Shutdown();
        }
    });
}

public class Protocolo 
{
    public static async Task RunChannel(MasterChannel channel)
    {
        // Associations and polls stuff...

        while (true)
        {
            await Task.Delay(10); // Set some delay or...

            await SomeJob(); // ...or do some job or ...

            switch (await GetInputAsync())  // ...or take github's example
            {
                case "x":
                    return;                    
                default:
                    Console.WriteLine("Unknown command");
                    break;
            }
        }
    }

    public static Task SomeJob()
    {
        return Task.Run(() => 
        {
            for (int i = 0; i < 5; i  )
            {
                 Thread.Sleep(200); // 200 x 5 = Total task for 1 second
            }
        });
    }

    public static Task<string> GetInputAsync()
    {
        return Task.Run(() => Console.ReadLine());
    }       
}
  • Related