是否有一种方法可以避免WPF MainWindow方法终止以避免线程化
本文关键字:方法 终止 MainWindow 线程 WPF 可以避免 一种 是否 | 更新日期: 2024-09-22 23:29:36
我目前正在进行一个WPF项目,该项目试图基于网络流源不断更新列表框。
据我所知,initializeComponent()
方法只有在MainWindow()
方法终止后才会实际显示WPF窗口。然而,我试图在其中有一个while(true)
循环,以便持续侦听来自服务器的更新信号,并使用适当的值更新列表框。
每个单独的方法都运行良好,只是由于while循环,它没有以当前形式打开WPF窗口。我试图避免使用后台更新线程来更新列表框,因为我知道我必须实现功能才能将列表框的线程"所有权"传递给线程,而且我不100%确定如何做到这一点。
有没有一个变通办法,或者更好的办法是,为了实现我所需的功能,我是否明显缺少了一些东西?
代码如下:
public MainWindow()
{
TcpClient client = new TcpClient();
client.Connect(serverAddress, port);
NetworkStream stream = client.GetStream();
numberOfPumps = 0; //initialize as 0 on startup.
handshake(stream);
InitializeComponent();
updatePumpList(stream);
updateListBox();
while(true)
{
updatePumpList(stream);
updateListBox();
}
}
updateListBox()
方法只是将字典中的项添加到列表框中。
private void updateListBox()
{
foreach(KeyValuePair<string, PumpItem> kvp in pumpDict)
{
pumpListBox.Items.Add(kvp.Key + ": " + kvp.Value.state);
}
}
不幸的是,您无法按照自己想要的方式进行操作。在Windows应用程序中,您必须让主(UI)线程运行。在该线程上执行的任何循环都将挂起整个应用程序,直到它完成为止。如果窗口是向上的,则看起来窗口是冻结的(因为它是)。如果它还没有启动,它看起来就像一个等待光标,永远。没办法。线程必须单独处理输入、更新窗口等。即使手动泵送消息循环(有人记得MFC吗?)也是一种糟糕的权宜之计。如果你让主线程按照设计者的意愿去做,Windows应用程序的工作效果最好。
当然,我们在主线程上做了很多事情,但这是在用户注意到任何延迟之前将控制权交回的快速事情。同步互联网访问从来都不够快,而且在进程的整个生命周期内持续的轮询循环是不可能的。
你有两种选择,在实践中都很温和。
您可以使用具有异步互联网访问功能的DispatchTimer。
另一个是您试图避免的工作线程。它们并没有那么糟糕。只需保留对Thread对象的引用即可在程序关闭时中止,当线程执行任何将触及任何UI的操作时(包括设置任何将引发PropertyChanged事件的属性),线程必须"调用"到UI线程中。
这根本不是什么大事:
Action act = () => Status = newStatus;
App.Current.Dispatcher.Invoke(act);
您是否考虑过为WPF窗口设置onLoad
事件处理程序,该事件处理程序将在WPF窗口显示后触发?然后,事件处理程序可以相应地运行while
循环。
或者,您可以让timer
在构造函数结束后几分钟启动一个事件,允许显示窗口,然后开始while循环。