проблемы с производительностью с WPF
Я работаю с пакетом dnp3 nuget, и я хочу реализовать его в WPF, и я добился этого, обратившись к этому примеру https://github.com/stepfunc/dnp3/blob/master/ffi/bindings/dotnet/examples/master/Program.cs Мне удалось реализовать его с помощью метода MVVM, где он динамически показывает сообщения, которые он получает (в гифке отображается ошибка, потому что он не создал другую программу, которая будет подключаться, но важно то, что она обновлено).
но я создал еще один гораздо более простой проект для демонстрации здесь, на github, в моем проекте создайте класс с именем protocol и вставьте весь основной пример, удалив основную функцию и изменив частные функции для общедоступных функций, а затем внутри моего MainWindow.xaml.cs запустить код
{
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
}
}
);
}
}
Я сделал профили производительности, и RunChannel - это то, что они многого требуют от процессора.
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
}
}
Я не знаю, почему, но без сообщения Пока полученные сообщения не обновляются (эти сообщения поступают в Регистратор), я должен поддерживать эту функцию всегда в рабочем состоянии, но я не знаю, как это сделать, не потребляя так много ресурсов процессора.
чтобы увидеть сообщения на выходе, вам нужно изменить
Console.WriteLine
к
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
}
}
1 ответ
Как уже было сказано ранее (ответ на вопрос о «проблеме с производительностью»):
- Ваш пустой цикл работает без каких-либо пауз или заданий. Вам нужно заполнить цикл каким-нибудь заданием или простой паузой (
Thread.Sleep(10)
/await Task.Delay(10)
). - У вашего метода RunChannel нет
await
, поэтому вы должны получить предупреждение CS1998 «В этом асинхронном методе отсутствует await» и, очевидно, поместить его в свой цикл.
На примере DNP3 Github есть
await GetInputAsync()
внутри
while
цикл, который ожидает ввода пользователя с
Console.ReadLine()
и возвращает введенную строку в
switch
утверждение.
Так:
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());
}
}