1

In public MainWindow() I call TestTask3(10000);. A TextBlock Text is bound to Answer in the XAML. The get is called and the initial value is displayed. I see the set call NotifyPropertyChanged. But the get is not called a second time to get the new value. I also have a button that changes Answer and that does change the TextBlock.

How to fix this or another approach? I want to keep the UI reactive and update some UI elements after a delay.

private int answser = -2;
public int Answer
{
    get { return answser; }
    set
    {
        if (answser != value)
        {
            answser = value;
            NotifyPropertyChanged("Answer");
        }
    }
}
public async void TestTask3(int delay)
{
    Debug.WriteLine($"TestTask3");
    int answer = -1;
    int i = await Task.Run(() =>
    {
        // … do compute-bound work here  
        Task.Delay(delay);
        answer = -1;
        return answer;
    });
    Debug.WriteLine($"TestTask3   {i}");
    Answer = answer;
    //return answer;
}
paparazzo
  • 44,497
  • 23
  • 105
  • 176
  • You shouldn’t use the same names for local variables and class fields, it’s very confusing. Have you tried putting a breakpoint in the setter and stepping through? – Dave M May 11 '18 at 01:37
  • Yeah this is confusing, i cant see how on earth the property Answer would get updated twice anyway (if i'm understanding you correctly) – TheGeneral May 11 '18 at 01:37
  • @DaveM As stated I see NotifyPropertyChanged called. That is how is see that. – paparazzo May 11 '18 at 01:41
  • @TheGeneral It gets updated if I change Answer in a button click event. – paparazzo May 11 '18 at 01:42

1 Answers1

3

Task.Delay(delay) is awaitable method.

Following solution works for me. I took a long loop calculation and it returns me result on UI after 10 seconds. Tested and working.

public async void TestTask3(int delay)
{
    int answer = -1;
    int i = await Task.Run(async () =>
    {
        // … do compute-bound work here  
        for (int j = 0; j < 100000000; j++)
        {
            answer += j;
        }

        await Task.Delay(delay);

        //answer = -1;
        return answer;
    });
    Answer = answer;
    //return answer;
}

Usage:

private async void Button_Click(object sender, RoutedEventArgs e)
{
    await TestTask3(10000);
}
Clemens
  • 123,504
  • 12
  • 155
  • 268
Gaurang Dave
  • 3,956
  • 2
  • 15
  • 34
  • So it was missing an async. Not sure how that broke it but I am just glad it is fixed. – paparazzo May 11 '18 at 01:53
  • I am glad to help. Cheers :) – Gaurang Dave May 11 '18 at 01:54
  • 2
    @paparazzo Since you should usually avoid `async void` methods (except event handlers), you may declare `public async Task TestTask3(int delay)` and make it `return answer`. Then call it like `Answer = await TestTask3(10000);` – Clemens May 11 '18 at 05:49
  • @Clemens That syntax throws a design time error for me. ` int ans = TestTask3(1000, token).Result;` is valid syntax but is hangs on that statement. – paparazzo May 11 '18 at 14:18
  • @Clemens This is how I wanted to do it as it returns a value. https://stackoverflow.com/questions/50281183/delay-in-a-task Problem is even with the answer it blocks on Delay. – paparazzo May 11 '18 at 14:22
  • It must be `int ans = await TestTask3(...)`. Don't use `Result`. See here: https://stackoverflow.com/q/27464287/1136211 – Clemens May 11 '18 at 15:25