问题
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