Reputation: 1325
I have a WPF C# projects with the below buttonClick event void:
public void ButtonClick(object sender, RoutedEventArgs e)
{
_worker.WorkerReportsProgress = true;
_worker.DoWork += (o, ea) =>
{
try
{
_class1.hithere();
}
catch (Exception exception)
{
MessageBox.Show(exception.Message);
}
};
_worker.ProgressChanged += (o, ea) =>
{
};
_worker.RunWorkerCompleted += (o, ea) =>
{
MessageBox.Show("Done");
};
_worker.RunWorkerAsync();
}
I have a folder in the application called InformationProviders than contains the Class1.cs file and I have implemented the correct using MyApplication.InformationProviders;
statement in the MainWindow.xaml.cs file that contains the button click event above.
I have also declared the Class1 class that is then called upon in the backgroundworker DoWork event correctly as such:
readonly Class1 _class1 = new Class1();
The Class1.cs file contains this little code made just to see if it worked and it doesn't unfortunately:
public class Class1
{
public void hithere()
{
MessageBox.Show("Hi, I'm working.");
}
}
What am I missing here???? I declared the class as public and (I believe) declared all that needed to be declared to make the process work...
All it does is display a message saying "Done", meaning it has completed the backgroundworker process (even though it did not do anything at all that was stated in the DoWork event. So pretty much, launching the worker and immediately considering it finished.
Regards and thanks,
Simon
Upvotes: 0
Views: 281
Reputation: 1325
I found the problem, i was using the Xceed.WPF.toolkit version of the MessageBox and it was just refusing to show that UI element in a backgroundWorker. Thanks for the help though it pointed me in the right direction. hoping this will help other people
Upvotes: 0
Reputation: 5650
Here's the tricky thing about running a multi-threaded application: only one thread has access to the UI and perform operations on it.
In case of your code, the BackgroudWorker
in it's background operation attempts to show a message using MessageBox
. This won't work - it's not being "fired" on the UI thread!
If you absolutely MUST perform UI operations from inside the BackgroundWorker
(which you shouldn't do - this is what the ProgressChanged
event is for) then you can use a Dispatcher
class.
Here's a short example:
private void Button_Click(object sender, RoutedEventArgs e)
{
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += (s, a) =>
{
this.Dispatcher.Invoke(new Action(() => MessageBox.Show("doing stuff")));
};
bw.RunWorkerCompleted += (s, a) =>
{
MessageBox.Show("done");
};
bw.RunWorkerAsync();
}
Also fun fact, if you use Dispatcher.Invoke
(as written above), then "doing stuff" will appear first, if you use Dispatcher.BeginInvoke
then "done" will appear first, because the other operation will be queued on the UI thread.
Here's the "politically correct" way to use the BackgroundWorker
:
bw.WorkerReportsProgress = true;
bw.DoWork += (s, a) =>
{
bw.ReportProgress(0, "doing stuff");
};
bw.ProgressChanged += (s, a) =>
{
MessageBox.Show(a.UserState as String);
};
Upvotes: 3