开发者

WPF ProgressBar Control Dispatch still blocking UI Thread

I am using WPF trying to run a Thread in the background that updates a progress bar. I don't wan to block the UI thread so I am running the following code. However the UI still blocked. It see开发者_如何学Cms so simple, what am I doing wrong?

       Dispatcher.BeginInvoke(
        (ThreadStart) delegate(){                   
            for(double i = progressBar_ChangeProgress.Minimum;
                i < progressBar_ChangeProgress.Maximum;
                i++)
                {
                    for (int b = 0; b < 100000000; b++) { }
                    progressBar_ChangeProgress.Value = i;
                }
            EnableAllInputControls();
        }, DispatcherPriority.Background);


Why not leverage the BackgroundWorker in this scenario...

        void Go()
        {
            BackgroundWorker worker = new BackgroundWorker();
            worker.WorkerReportsProgress = true;
            worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);
            worker.DoWork += new DoWorkEventHandler(worker_DoWork);
            worker.RunWorkerAsync();
        }

        void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            progressBar_ChangeProgress.Value = e.ProgressPercentage;
        }

        void worker_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;
            for (int b = 0; b < 100; b++) 
            {
                Thread.Sleep(100);
                worker.ReportProgress(b);
            }
        }

UPDATE:

If you are wanting to use the Dispatcher; set the priority to Normal and perform the processing on the background thread then calling a method on the UI thread to provide the update.

        void Go()
        {
            ThreadStart start = delegate()
            {
                //this is taking place on the background thread
                for (int i = 0; i < 100; i++)
                {
                    //this is slowing things down; no real relevance
                    Thread.Sleep(100);

                    //this will marshal us back to the UI thread
                    Dispatcher.Invoke(DispatcherPriority.Normal,
                                         new Action<int>(Update), i
                                         );
                }

            };

            new Thread(start).Start();
        }

        void Update(int value)
        {
            //this is taking place on the UI thread
            _progressBar.Value = value;
        }


The Dispatcher is just a mechanism to run a bit of code on the UI thread at a later time. The priority you're passing in controls when it will get executed, not any type of thread priority. The contents of your delegate in this case are getting run on the UI thread. Using a BackgroundWorker as mentioned by Aaron would certainly help here.

Also I might point out that usually a progress bar shows how close a task is to completing. If you don't know how long something is going to take or have no way of measuring progress, you can use an Indeterminate progress bar. Only update the value if you have some meaningful information. (though you may have just provided this for demonstration purposes)


Everything inside BeginInvoke is being run on the UI thread and so it will block.

What you need to do is run any time intensive code in your thread and then just update the UI inside the Invoke.

You want something more like this:

for (double i = progressBar_ChangeProgress.Minimum;
    i < progressBar_ChangeProgress.Maximum;
    i++)
{
  for (int b = 0; b < 100000000; b++) { }
  Dispatcher.Invoke((ThreadStart) delegate(){                   
    progressBar_ChangeProgress.Value = i;
  });
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜