主线程中的长操作会强制UI挂起

时间:2016-02-03 09:52:23

标签: wpf vb.net

我有一个很长的操作,可以在主UI上创建一些工具。

当我运行此操作时,UI会挂起。 我想更新ProgressBar以指示操作状态百分比,但它不会更新。

我的代码如下所示:

Sub DoWork()
    DoLongOperation()
End sub

sub DoLongOperation()
 For K as integer = 0 to 50
   'Here I create tools and add them to a StackPanel in the window
   'While doing this I update a progressBar value
   ProgressBar1.value=Some value
 Next
End sub

我该怎么做? 我尝试了异步等待,但它无法处理为主UI创建工具的操作。

3 个答案:

答案 0 :(得分:0)

ProgressBar未更新的原因是您仍然阻止主线程。应该在另一个线程中调用您的长操作。所以你可以使用例如Task.Run方法。 还有一件事要记住,在另一个线程中你不能改变任何UI,你应该使用你的窗口的Dispatcher属性。

private void Button_Click(object sender, RoutedEventArgs e)
{
    Task.Run(() =>
    {
        for(int i = 0; i < 50; i++)
        {
            Thread.Sleep(1000); // some long operation

            var progress = i*2;

            Dispatcher.Invoke(() =>
            {
                progressBar1.Value = progress;
            });
        }
    });
}

答案 1 :(得分:0)

如前所述,为了更新UI,或者在执行非常长的操作时仍然使其解锁和可用,您必须在其他线程中执行该操作。您可以使用BackgroundWorker来执行此操作。如果您不想为新线程创建新方法,您可以委派它们,这样您就可以这样做:

Imports System.ComponentModel
Sub DoLongOperation()
    Dim bgWorker As New System.ComponentModel.BackgroundWorker()
    bgWorker.WorkerReportsProgress = True

    AddHandler bgWorker.DoWork, 
        Sub(sender, args)
            For K as integer = 0 to 50
                'Here I create tools and add them to a StackPanel in the window
                'While doing this I update a progressBar value

                bgWorker.ReportProgress(123)
            Next
        End Sub

    AddHandler bgWorker.ProgressChanged,
        Sub(sender, args)
            ProgressBar.Value = args.ProgressPercentage
        End Sub

    AddHandler bgWorker.RunWorkerCompleted,
        Sub(sender, args)

        End Sub

End sub

由于您无法在StackPanel上的其他帖子中添加/删除或执行其他操作,因此您可以将要添加的项目放入bgWorker.ReportProgress()方法,然后从{{1事件所以就是这样:

.ProgressChanged

答案 2 :(得分:0)

我明白了。我把我的创作分为50个部分。在创建一个工具结束时,我可以设置进度条。之后,我可以创建第二个。然后继续。