是否有一种方法可以避免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);
    }
}

是否有一种方法可以避免WPF MainWindow方法终止以避免线程化

不幸的是,您无法按照自己想要的方式进行操作。在Windows应用程序中,您必须让主(UI)线程运行。在该线程上执行的任何循环都将挂起整个应用程序,直到它完成为止。如果窗口是向上的,则看起来窗口是冻结的(因为它是)。如果它还没有启动,它看起来就像一个等待光标,永远。没办法。线程必须单独处理输入、更新窗口等。即使手动泵送消息循环(有人记得MFC吗?)也是一种糟糕的权宜之计。如果你让主线程按照设计者的意愿去做,Windows应用程序的工作效果最好。

当然,我们在主线程上做了很多事情,但这是在用户注意到任何延迟之前将控制权交回的快速事情。同步互联网访问从来都不够快,而且在进程的整个生命周期内持续的轮询循环是不可能的。

你有两种选择,在实践中都很温和。

您可以使用具有异步互联网访问功能的DispatchTimer。

另一个是您试图避免的工作线程。它们并没有那么糟糕。只需保留对Thread对象的引用即可在程序关闭时中止,当线程执行任何将触及任何UI的操作时(包括设置任何将引发PropertyChanged事件的属性),线程必须"调用"到UI线程中。

这根本不是什么大事:

Action act = () => Status = newStatus;
App.Current.Dispatcher.Invoke(act);

您是否考虑过为WPF窗口设置onLoad事件处理程序,该事件处理程序将在WPF窗口显示后触发?然后,事件处理程序可以相应地运行while循环。

或者,您可以让timer在构造函数结束后几分钟启动一个事件,允许显示窗口,然后开始while循环。