0

I am trying to update property on my main Thread, which is bind to ProgressBar. In viewmodel I have the bellow code, which is not working.

TaskScheduler uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();

Task task = Task.Factory.StartNew(() =>
{
    DoLongRunningWork();

}).ContinueWith(_=>
{   

    ApplicationStatus = "Task finished!";

}, TaskScheduler.FromCurrentSynchronizationContext());


DoLongRunningWork()
{
    // Alot of stuff

    Task.Factory.StartNew(() =>
    {
        ProgressBarValue += progressTick;
    }).Start(uiScheduler);
}
Jim
  • 2,760
  • 8
  • 42
  • 66
  • Explain `not working` – Sriram Sakthivel Mar 03 '14 at 12:52
  • The ProgressBarValue += progressTick; is not updated – Jim Mar 03 '14 at 12:53
  • Which version of framework? and what are the type of variables `ProgressBarValue` and `progressTick`? – Sriram Sakthivel Mar 03 '14 at 12:54
  • .NET 4 , both are double type.... The code without threading is working fine, hoewever In the above Task the ProgressBarValue is not updated causing ProgressBar to not show any progress – Jim Mar 03 '14 at 12:57
  • Did you tried to debug the program? – Sriram Sakthivel Mar 03 '14 at 12:58
  • how you are binding on ProgressBarValue – BRAHIM Kamel Mar 03 '14 at 12:58
  • 1
    You are updating the `ProgressBarValue` in a task which is in another task. It should be updated by the UI thread. Or you should use `SomeControl.Invoke` BTW: the outer task completes immediately since it only creates another task(doing the actual work) and then finishes – L.B Mar 03 '14 at 13:01
  • Hmm.. I do specify the uiScheduler which is main Thread? Since I am using MVVM and I think I shoudnt/can't use SomeControl.Invoke . This is why I am asking of updating a property which is found in Main thread – Jim Mar 03 '14 at 13:06
  • 1
    `Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() => ProgressBarValue += progressTick));` as in this answer here: http://stackoverflow.com/a/1644254/2609288 – Baldrick Mar 03 '14 at 13:15
  • You should be getting an exception that explains what the issue is. (Hint: you can't start `Task` twice.) – svick Mar 03 '14 at 14:04
  • Application.Current.Dispatcher.BeginInvoke(new Action(() => ProgressBarValue += progressTick)); did the job – Jim Mar 03 '14 at 14:14

1 Answers1

4

If the property ProgressBarValue is bound to a WPF element, then the only thread that can update the ProgressBar is the very thread that created it.

So, my assumption is that the class that contains ProgressBarValue also implements INotifyPropertyChanged. This means that you have some logic that raises the event PropertyChanged.

I would create a method that raises the event, and always does so using the Dispatcher. (The Dispatcher allows you to call functions on the thread that created your WPF controls.)

private void raisePropertyChanged(string name)
{
  Dispatcher.InvokeAsync(()=>
  {
    if(PropertyChanged != null)
      PropertyChanged(this, new PropertyChangedEventArgs(name));
  });
}

This will always update the ProgressBar on the proper thread.

poy
  • 10,063
  • 9
  • 49
  • 74
  • This property as well as whole class already implements INotifyPropertyChanged – Jim Mar 03 '14 at 13:42
  • Then all you need to do is use the `Dispatcher` whenever you raise the `PropertyChanged` event. – poy Mar 03 '14 at 18:40