有一个第三方 TelnetClient 类。在它的帮助下,只需按一下按钮,我就可以建立连接并订阅传入的消息。通过按下另一个按钮,我发送一个命令来读取远程目录。第三方类源可用,它基于 TPL,并且HandleMessageReceived不是从 GUI 线程调用的,所以我被迫使用 (Begin)Invoke
TelnetClient tc = null;
private async void buttonLogin_Click(object sender, EventArgs e)
{
tc = new TelnetClient("host", 23, TimeSpan.FromSeconds(3),
new System.Threading.CancellationToken());
tc.MessageReceived += HandleMessageReceived;
await tc.Connect();
await tc.Send("username");
await tc.Send("password");
}
private void HandleMessageReceived(object sender, MessageEventArgs mea)
{
this.BeginInvoke(new Action(() =>
{
textBox1.Text += mea.Message;
}));
}
private async void buttonSend_Click(object sender, EventArgs e)
{
await tc?.Send("dir");
}
该代码有效,但很糟糕:
1) 运行时间过长(几分钟)。同一主机上的任何普通 telnet 应用程序dir执行命令的速度要快很多倍(大约一秒)。
2) 阻止 GUI。
问题
1) 为什么 GUI 被阻止?如何避免?
2)性能不佳的原因是什么?如何避免?
20K 电话是很多。UI 根本没有时间接收您的消息。
做不同的事情。如果您
TelnetClient的 API 带有Stream'th(如在TcpClient'e'中),请使用它并逐行阅读。如果不是,则将行缓冲
HandleMessageReceived到适当的大小,并在达到限制时或经过一段合理的时间(至少十分之一秒)后发送到 UI。如果你碰巧在使用响应式扩展,那么这对他们来说是一个很好的目标(管理背压):
如果您写入文件,那么也这样做吗?如果同时有很多流?
“进程无法接收……”——你要背诵^^
有必要使用一个单独的写入线程处理它,观察指定的时间间隔,以便两者都足够快地更新并且GUI不会挂起。
并将此架构从一个项目复制到另一个项目。即使看起来没有必要。
我自己做,但你可以找一些现成的东西,他们在上面提到过 Reactive。