Reputation: 129
I'm developping an application that should run a new task , makes some stuff and return a list of objects...
when spawning the new task , i need to simulate in my UI thread a progressbar changing in a for loop... and after the task completion , i have to update my view ( by updating the values of my ViewModel properties as i'm using MVVM pattern).
the problem is that when the task is launched, the GUI freezes and the progress bar is not updated! i thought that tasks are run in background on a sperate thread ( as they are pooled). so why my GUI is blocked??
here is a snippet of my code :
Task<List<Items>> myTask = Task.Factory.StartNew(() => queryHandler.GetItemssStatistics(items, sec, buyer, seller, From, To));
//Here is the simulation of ProgressBar changing that i need to be done when task is started
for (int i = 0; i < 100; i++)
{
Thread.Sleep(100);
StatusValue = i+1;
}
//Here is the section i need to do once the task finishes its execution to update my VM
//Wait for the task to finish its execution and retreive results:
List<Items> _tempResults = myTask.Result;
foreach (Items d in _tempResults)
{
ResultsList.Add(d);
}
if (ResultsList.Count == 0)
{
MessageBox.Show("Sorry, No items matched the defined research criteria!", "Warning",
MessageBoxButton.OK,
MessageBoxImage.Warning, MessageBoxResult.OK, MessageBoxOptions.ServiceNotification);
}
else
{
//Show items:
ResultsAvailable = Visibility.Visible;
}
Upvotes: 0
Views: 3319
Reputation: 22739
There are a few problems with your code:
Thread.Sleep
on the UI threadTask<T>.Result
again on the UI thread - which blocks until the task has been completed.You can do a few things:
Use ProgressBar.IsIndeterminate = true
to show a marquee-style progress bar instead of faking the progress update or use a DispatcherTimer
to update the progress bar.
Use async/await
:
async Task GetItems()
{
List<Items> tempResults = await Task.Run(() => queryHandler.GetItemssStatistics(...));
// the following will be executed on the UI thread automatically
// after the task is done, keeping the UI responsive
foreach (Items d in _tempResults)
{
ResultsList.Add(d);
}
}
Upvotes: 2
Reputation: 13207
You are still stopping the UI from working, because you are calling Thread.Sleep
on it. If you want your progress-bar to update, run another thread, or try to integrate the increasing of the progress-bar in your task.
Looking at your code, it would be better to do the update of the progress-bar in your task!
You are making the user wait for 10000 ms, if your task finishes before, the user has to wait...
Access the dispatcher of the progress-bar in your task, when one items has been progressed and do like
//process item
if(progressBar.Dispatcher.CheckAccess()){
progressBar.Value += 1; //maybe calculate the number of items you are processing
}
else {
//send a delegate to the dispatcher
MyDelegate myDel = new MyDelegate(delegate() {
progressBar.Value += 1;
});
progressBar.Dispatcher.Invoke(myDel);
}
The delegate's signature could be something like:
public void MyDelegate();
Upvotes: 0