如何在进行涉及访问UI控件的耗时工作时不阻塞UI

本文关键字:UI 工作 控件 访问 | 更新日期: 2023-09-27 18:27:24

我有一个方法很耗时,因此我一直在尝试实现BackgroundWorker,但它不允许访问我已经阅读并尝试过的UI控件(对其进行黑客攻击),但没有成功。

我的方法是:创建一个新的BitmapImage,将源设置为本地或流式(参数),将其写入用于ConvertToGrayscale的新WriteableBitmap,然后将BW Copy保存到文件夹中的IsolatedStorage

所以这一切发生得很快。但是,只有当我说少于25个源图像时。如果我有大约100多个图像,这需要相当长的时间,比如20秒或更长时间,因此,我想在同一个PhoneApplicationPage中显示ProgressBar,但我一直在努力解决如何在该方法工作时不阻塞UI并显示ProgressBar。

这是我的代码:

void GetImages()
    {
        if (!myIsolatedStorage.DirectoryExists("ImagesBW") && !_appsettings.Contains("_update"))
        {
            myIsolatedStorage.CreateDirectory("ImagesBW ");
            for (int i = 0; i < coll.Desserts.Count; i++)
            {
                BitmapImage bmp = new BitmapImage();
                bmp.CreateOptions = BitmapCreateOptions.None;
                if (coll.Desserts[i].HasAssociatedImage)
                {
                    bmp.SetSource(coll.Desserts[i].GetImage());
                    WriteableBitmap wb = new WriteableBitmap(bmp);
                    ConvertToGrayscale(wb);
                    BitmapImage bit = ConvertWBtoBI(wb);
                    SaveBWCopy(bi, i.ToString());
                }
                else
                {
                    bmp.UriSource = new Uri("/Assets/Images/MissingArt.png", UriKind.Relative);
                    WriteableBitmap wb = new WriteableBitmap(bmp);
                    ConvertToGrayscale(wb);
                    BitmapImage bit = ConvertWBtoBI(wb);
                    SaveBWCopy(bi, i.ToString());
                }
            }
            _appsettings["_firstLaunch"] = "false";
            _appsettings.Save();
        }
        else if (myIsolatedStorage.DirectoryExists("ImagesBW ") && _appsettings.Contains("_update"))
        {
            string[] files = myIsolatedStorage.GetFileNames("ImagesBW/*");
            for (int s = 0; s < files.Length; s++)
            {
                myIsolatedStorage.DeleteFile("ImagesBW/" + s + ".jpg");
            }
            myIsolatedStorage.DeleteDirectory("ImagesBW");
            myIsolatedStorage.CreateDirectory("ImagesBW");
                            for (int i = 0; i < coll.Desserts.Count; i++)
            {
                BitmapImage bmp = new BitmapImage();
                bmp.CreateOptions = BitmapCreateOptions.None;
                if (coll.Desserts[i].HasAssociatedImage)
                {
                    bmp.SetSource(coll.Desserts[i].GetImage());
                    WriteableBitmap wb = new WriteableBitmap(bmp);
                    ConvertToGrayscale(wb);
                    BitmapImage bit = ConvertWBtoBI(wb);
                    SaveBWCopy(bi, i.ToString());
                }
                else
                {
                    bmp.UriSource = new Uri("/Assets/Images/MissingArt.png", UriKind.Relative);
                    WriteableBitmap wb = new WriteableBitmap(bmp);
                    ConvertToGrayscale(wb);
                    BitmapImage bit = ConvertWBtoBI(wb);
                    SaveBWCopy(bi, i.ToString());
                }
            }
            _appsettings.Remove("_update");
            _appsettings.Save();
        }
        btnStart.IsEnabled = true;
    }

如何在进行涉及访问UI控件的耗时工作时不阻塞UI

Backgroundworker是您的最佳选择。web上有大量的资源来实现它。但其背后的想法是Backgroundworker在独立于UI的线程中运行。您可以通过两种方法访问主线程UI,一种是委托,另一种是通过Backgroundworker的ProgressChanged方法,该方法可以访问UI线程。

假设你有这个。

    public MainWindow()
    {
        InitializeComponent();
       //if you want to disable you button you can do it here 
        BackgroundWorker _bw = new BackgroundWorker();
        _bw.DoWork += new DoWorkEventHandler(_bw_DoWork);
        _bw.WorkerReportsProgress = true;
        _bw.ProgressChanged += new ProgressChangedEventHandler(_bw_ProgressChanged);
        _bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_bw_RunWorkerCompleted);
        _bw.RunWorkerAsync();
       //or here
       //Display progress bar here too
    }
    void _bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        //this can give you access to the UI after work is completed
        // to check that everything is ok  or hide progress bar
    }
    void _bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
       //this will give you access to the UI in the middle of you work like update progress bar
    }
    void _bw_DoWork(object sender, DoWorkEventArgs e)
    {
        //actual work here including GetImages
        //work work work
       GetImages();
    }

在SaveBWCopy之后的getimages方法中,您可以添加此来更新进度条

        _bw.ReportProgress(int progress ) 
        //progress is the percentage you want to send to progress bar to display that is going to  be in the e eventargument you passed.