Reputation: 1921
in WPF application I load a list of business objects by WCF to a listbox.
I want to load it in another thread and display a progressbar window.
But how? I need to call WCF service in the second thread and return its return value to the first (UI) thread. And this is the point I don't know. How to return? Or what should be the correct workflow of calling for data at background and displaying of progress?
Now I:
- show the progress window
- create a new thread and call the WCF service
- return values <-- I don't know
- close window
But - is this workflow right?
I don't want to use a backgroundworker because I can call many different WCF services, not only one I could write into the DoWork method.
I have a WCFClient class in which I call all services I need. Here is a one of the methods (all methods are same only calls different services):
public class Client
{
public List<BusinessDto> GetBusinesses(int userID)
{
OnConnecting();
ServiceClient client = null;
BusinessDto[] dtos = null;
try
{
client = new ServiceClient();
dtos = client.GetBusinesses(userID);
}
catch
{
MessageBox.Show(Properties.Resources.ConnectionNotSucessful, Properties.Resources.ApplicationName, MessageBoxButton.OK, MessageBoxImage.Error);
}
finally
{
if (client != null) client.Close();
OnClosing();
}
return dtos.ToList();
}
}
I'm catching an Onconnecting and OnClosing events of WCFClient and opening and closing a new window with progressbar.
But I do not call WCF services in a new thread, because I don't know how.
Thanks, I'm trying do that unsuccessfuly for a two days.
Upvotes: 1
Views: 560
Reputation: 178770
BackgroundWorker
is your friend. It does the thread marshalling for you, leaving you to worry about only doing the actual work.
Upvotes: 0
Reputation: 96860
I don't want to use a backgroundworker because I can call many different WCF services, not only one I could write into the DoWork method.
Well, first, you can decide which of many DoWork methods you want to call at the time you prepare the BackgroundWorker. But you can also (and this is probably more maintainable) write a DoWork method of arbitrary complexity. You can write a DoWork method that takes an argument of type Client
, and have it call a member method on that object, for instance. There's absolutely nothing limiting about this method.
The way I'd implement a progress bar window:
Task
class that exposes three methods: SetUp
, Execute
, and TearDown
, as well as a Status
property, which is a struct containing int PercentComplete
and string Message
. Implement INotifyPropertyChanged
.protected UpdateStatus
method that updates Status
and raises PropertyChanged
.ShowDialog(Task t)
method. In that method, call t.SetUp()
, then create a BackgroundWorker
. t.PropertyChanged
and have the handler raise the BackgroundWorker
's ProgressChanged
event. BackgroundWorker
's ProgressChanged
event handler use t.Status
to update the UI, BackgroundWorker
's DoWork
event handler call t.Execute()
.RunWorkerCompleted
event handler both handle exceptions (do not neglect this!) and call t.TearDown()
.Task
subclasses as needed.Task
, set whatever properties it needs, and then call ProgressBarWindow.ShowDialog(t)
. This will display the window and block and wait while the background process runs, updating the UI as it goes; it will return after t.TearDown()
gets called.Upvotes: 2