繁体   English   中英

使用后台工作程序并更新UI

[英]Using background worker and updating UI

当我需要执行耗时很长的动作时,可以像这样在BackgroundWorker中调用它,因此它不会冻结UI。

BackgroundWorker bgWorker = new BackgroundWorker();

bgWorker.DoWork += (s, e) => { 
    //Do something long lasting
    for(int i = 0; i < x; i++){

        //Performing action i of x

        //While doing so update the progressbar
        prgBar.Dispatcher.Invoke(() =>{
            prgBar.Value += ((i / x) * 100.0);
        });

    }
};  

bgWorker.RunWorkerCompleted += (s, e) => { 
    //Finish up things
}; 
bgWorker.RunWorkerAsync();

这是更新UI的“方法”还是“未完成”? 相同的问题适用于BackgroundWorker(也许只是启动一个新线程而不是BackgroundWorker?)

如果需要从后台线程更新某些UI组件,则应使用Dispatcher来编组对主线程的调用。 话虽这么说,您似乎正在尝试更新一些进度条。 BackgroundWorker类已经提供了一种机制。 因此,您只需在窗体上具有一个ProgressBar控件,然后:

var bgWorker = new BackgroundWorker();

// Specify that this worker supports progress
bgWorker.WorkerReportsProgress = true;

bgWorker.OnProgressChanged += e => 
{
   // This is called on the main thread. It safe to update your UI components here
   myProgressBar.Value = e.ProgressPercentage;
};

bgWorker.DoWork += (s, e) => 
{ 
    // Do something long lasting
    for(int i = 0; i < x; i++) {
        //Performing action i of x

        // While doing so notify the subscribers of the progress event
        var progress = (int)((i / x) * 100.0);
        bgWorker.ReportProgress(progress);
    }
};  

bgWorker.RunWorkerCompleted += (s, e) => 
{ 
    //Finish up things
}; 

bgWorker.RunWorkerAsync();

不它不是。 主要问题是您的进度栏-它位于后台工作线程中,而不是UI线程中。 它也从未真正挂在任何东西上-它在哪里显示?

正确的方法是拥有一个包含进度条的表单,并在启动后台工作程序之前在UI线程中打开它(或仅开始对其进行拍摄),然后在完成时将其隐藏。

尽管此刻出现未正确初始化的进度条,但使用Dispatcher的更新逻辑是“正确的”。 但是调用是您必须要做的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM