WPF 的性能问题
performance issues with WPF
我正在使用dnp3 nuget包,我想在WPF中实现它,我参考这个例子实现了https://github.com/stepfunc/dnp3/blob/master/ffi/bindings/dotnet/examples/master/Program.cs
我设法通过 MVVM 方法实现它,它动态显示它收到的消息(在 gif 中它显示错误,因为它没有创建另一个将连接的程序,但重要的是它正在更新)。
但我创建了另一个更简单的项目来在 github 上进行演示,在我的项目中创建一个 class 调用协议并粘贴所有主示例删除主函数并更改私有public 函数的函数,然后在我的 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 是他们对 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
}
}
我不知道为什么但是如果没有 While received messages are not updated, (these messages arrived in the Logger) 我必须让这个功能一直保持活动状态但我不知道如何在不消耗的情况下做到这一点这么多 CPU
要查看输出中的消息,您必须将 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
}
}
如前所述(回答“性能问题”):
- 你的空
while
循环 运行 没有任何暂停或工作。您需要用一些工作或简单的暂停来填充循环 (Thread.Sleep(10)
/await Task.Delay(10)
)。
- 您的 RunChannel 方法没有任何
await
,因此您应该收到 CS1998 警告“此异步方法缺少 'await'”,显然,将其放入您的 while
循环中。
在 DNP3 Github 示例中,while
循环中有 await GetInputAsync()
,等待用户输入 Console.ReadLine()
和 returns 输入字符串到 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());
}
}
我正在使用dnp3 nuget包,我想在WPF中实现它,我参考这个例子实现了https://github.com/stepfunc/dnp3/blob/master/ffi/bindings/dotnet/examples/master/Program.cs 我设法通过 MVVM 方法实现它,它动态显示它收到的消息(在 gif 中它显示错误,因为它没有创建另一个将连接的程序,但重要的是它正在更新)。
但我创建了另一个更简单的项目来在 github 上进行演示,在我的项目中创建一个 class 调用协议并粘贴所有主示例删除主函数并更改私有public 函数的函数,然后在我的 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 是他们对 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
}
}
我不知道为什么但是如果没有 While received messages are not updated, (these messages arrived in the Logger) 我必须让这个功能一直保持活动状态但我不知道如何在不消耗的情况下做到这一点这么多 CPU
要查看输出中的消息,您必须将 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
}
}
如前所述(回答“性能问题”):
- 你的空
while
循环 运行 没有任何暂停或工作。您需要用一些工作或简单的暂停来填充循环 (Thread.Sleep(10)
/await Task.Delay(10)
)。 - 您的 RunChannel 方法没有任何
await
,因此您应该收到 CS1998 警告“此异步方法缺少 'await'”,显然,将其放入您的while
循环中。
在 DNP3 Github 示例中,while
循环中有 await GetInputAsync()
,等待用户输入 Console.ReadLine()
和 returns 输入字符串到 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());
}
}