C# WPF-在后台运行长操作时更新元素

C# WPF-在后台运行长操作时更新元素,c#,wpf,user-interface,dispatcher,C#,Wpf,User Interface,Dispatcher,我正在构建一个简单的WPF应用程序,在应用程序中的许多地方,我有很长的操作时间,在此期间,我想更新UI,这样应用程序看起来就不会崩溃。 例如,我有一个登录按钮,当我按下它时,除了验证所有凭证外,它还加载该特定用户数据的二进制数据库。对于一个拥有大量数据的用户来说,这可能需要3-5秒,而对于另一个用户来说,这可能是即时的 我想要的是能够在完成按钮单击事件之前更新其他元素,并且我想要按照代码的确切顺序进行更新 以下是登录按钮单击事件: private void btnLogin_Click(obje

我正在构建一个简单的WPF应用程序,在应用程序中的许多地方,我有很长的操作时间,在此期间,我想更新UI,这样应用程序看起来就不会崩溃。 例如,我有一个登录按钮,当我按下它时,除了验证所有凭证外,它还加载该特定用户数据的二进制数据库。对于一个拥有大量数据的用户来说,这可能需要3-5秒,而对于另一个用户来说,这可能是即时的

我想要的是能够在完成按钮单击事件之前更新其他元素,并且我想要按照代码的确切顺序进行更新

以下是登录按钮单击事件:

private void btnLogin_Click(object sender, RoutedEventArgs e) {
            var username = txtUsername.Text;
            var password = pswBox.Password;
            lblLoginStatus.Visibility = Visibility.Visible;
            if (string.IsNullOrWhiteSpace(username) || string.IsNullOrWhiteSpace(password)) {
                lblLoginStatus.Content = "Both username and password cannot be empty!";
            } else {
                prgLogin.Visibility = Visibility.Visible; //Progress bar that should be visible while the long operation is running.
                var login = Adb.Login(username, password); //Long operation
                prgLogin.Visibility = Visibility.Collapsed; //Upon completion of the operation, hide the progress bar.
                if (!login) {
                    lblLoginStatus.Content = "Wrong Credentials!";
                } else { //This basically exits the login page/window
                    LoginPage.Visibility = Visibility.Collapsed;
                    GeneralPage.Visibility = Visibility.Visible;
                }
            }
        }
正如你们所看到的,我并没有看任何花哨的动画,甚至没有进度报告。进度条是不确定的,我对其进行了样式设置,使其仅以可见性触发器开始和结束

我的问题是,与我的逻辑相反,代码的运行顺序与编写的顺序完全相同,在按下按钮后,它看起来就像卡住了一样,在操作结束之前,没有其他元素被更新,此时登录窗口隐藏了自己,使我所有创建愉快的UI的努力都变得毫无价值

我试过使用:

Dispatcher.CurrentDispatcher.Invoke(/*Whatever element update I want*/);
但这没有帮助,结果是一样的

我在网上看到了一些类似问题的复杂而漫长的解决方案,我试图实现它们,即使只是为了测试,我现在把它弄乱了大约4个小时,但没有结果

正如上面所述,我的应用程序的其余部分充满了如下部分:

progressBar.Visibility = Visibility.Visible;
var operation = AnyLongOperation()
prgLogin.Visibility = Visibility.Collapsed;

因此,我正在寻找一个简单的解决方案,我将能够适应整个应用程序。

用户界面冻结,因为您的程序运行在一个线程上,
Adb。登录
会阻止主线程,因此用户界面无法更新,您必须将登录功能移动到另一个线程,并从那里更新进度,这应该会有所帮助,实现或使登录方法异步调用
Adb并不太复杂。从UI线程(正如您在这里所做的)登录(用户名、密码)
将阻止该线程,从而阻止UI。使登录方法异步并等待它,或将其包装到等待的任务中。@Clemens我试图将其包装到任务中,然后使用Task.WaitAll(任务),但它仍然被卡住。。。我认为问题在于,如果我使用async await,那么我需要在事件退出进行验证之前获得结果,而在它等待时,它会继续所有其他UI操作?是的。使处理程序方法异步,即,
private async void btnLogin_单击(对象发送方,RoutedEventArgs e)
,然后调用
var login=wait Task.Run(()=>Adb.login(用户名,密码))
@Clemens我想你应该做
var operation=Task.Factory.StartNew(()=>Adb.Login(用户名、密码))然后
var登录=等待操作还是相同?您只能在特殊情况下使用Task.Factory.StartNew。如前所述,使用Task.Run。您现在既不会明确地运行线程,也不会使用BackgroundWorker。Async/await是一种方式。