WPF: Asynchronous progress bar

左心房为你撑大大i 提交于 2019-12-13 14:18:36

问题


I'm trying to create a progress bar that will work asynchronously to the main process. I'm created a new event and invoked it however everytime I then try to perform operations on the progress bar I recieve the following error:

"The calling thread cannot access this object because a different thread owns it"

The following code is an attempt to send an instance of the progress bar to the event as an object, it obviously failed but it gives you an idea of what the code looks like.

    private event EventHandler importing;

    void MdbDataImport_importing(object sender, EventArgs e)
    {
        ProgressBar pb = (ProgressBar)sender;
        while (true)
        {
            if (pb.Value >= 200)
                pb.Value = 0;

            pb.Value += 10;
        }
    }

    private void btnImport_Click(object sender, RoutedEventArgs e)
    {
        importing += new EventHandler(MdbDataImport_importing);
        IAsyncResult aResult = null;

        aResult = importing.BeginInvoke(pbDataImport, null, null, null);

        importing.EndInvoke(aResult);
    }

Does anyone have ideas of how to do this.

Thanks in advance SumGuy.


回答1:


You should use something like this

pb.Dispatcher.Invoke(
                  System.Windows.Threading.DispatcherPriority.Normal,
                  new Action(
                    delegate()
                    {

                        if (pb.Value >= 200)
                            pb.Value = 0;

                        pb.Value += 10;
                    }
                ));

in your while loop




回答2:


You need to delegate pbDataImport to the dispatcher. Only the GUI-dispatcher can make changes to GUI controls :)




回答3:


I've looked into it further and the asynchronous method will work as well as the following method from MSDN.

In XAML:

<ProgressBar Width="100" Height="20" Name="progressBar1">
    <ProgressBar.Triggers>
        <EventTrigger RoutedEvent="ProgressBar.Loaded">
            <BeginStoryboard>
                <Storyboard>
                    <DoubleAnimation Storyboard.TargetName="progressBar1"  From="0" To="100" Duration="0:0:5"  />
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </ProgressBar.Triggers>
</ProgressBar>

In C#:

        ProgressBar progbar = new ProgressBar();
        progbar.IsIndeterminate = false;
        progbar.Orientation = Orientation.Horizontal;
        progbar.Width = 150;
        progbar.Height = 15;
        Duration duration = new Duration(TimeSpan.FromSeconds(10));
        DoubleAnimation doubleanimation = new DoubleAnimation(100.0, duration);
        progbar.BeginAnimation(ProgressBar.ValueProperty, doubleanimation);

My problem was that I was performing a stored procedure when I wanted the progress bar to perform and this holds the process up and therefore makes the progress bar a bit rubbish, even when asynchronous.

I suppose the other possiblilty would be to make the stored procedure actions asynchronous, what do you guys think?

Cheers, SumGuy

Edit (17 May 2010)

It seems a lot of people are interested in this post so I thought I'd add this. I found an excellent piece which describes Asynchronous work in WPF in great detail along with a tasty bit on progress bars:

http://www.codeproject.com/KB/WPF/AsynchronousWPF.aspx




回答4:


I like using MVVM and a BackgroundWorker a little bit better. Here is a sample of doing that.

A Progress Bar using WPF’s ProgressBar Control, BackgroundWorker, and MVVM



来源:https://stackoverflow.com/questions/1152768/wpf-asynchronous-progress-bar

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!