1

There is something I can't understand with chaining tasks and executing tasks on Main Thread.

I need to chain 2 tasks when my model updates: (1)update then (2)check status. So I use continueWith to achieve this :

// Update the model
Debug.WriteLine($"BaseModel<{typeof(T)}> - Launching Update Process");
Status = ModelStatus.Updating;
Task Update = Task.Run(() => UpdateDataSpeciliazed());
Debug.WriteLine($"BaseModel<{typeof(T)}> - Update Process Lauchned");

// And check if the status of the model is updated
Update.ContinueWith(antecedent =>
{
    lock (IsLocked)
    {
        Debug.WriteLine($"BaseModel<{typeof(T)}> - Checking ModelStatus ({Status})");

        // UpdateDataSpeciliazed must update the status accordingly
        if (Status == ModelStatus.Updating)
        {
            Debug.WriteLine($"BaseModel<{typeof(T)}> - UpdateDataAsync - ModelStatus not updated");
            throw new NotImplementedException();
        }

        Debug.WriteLine($"BaseModel<{typeof(T)}> - ModelStatus Checked");
    }
});

When the function UpdateDataSpeciliazed of the derived class is simple (no child task), the process behave like expected. But when UpdateDataSpeciliazed launch some actions on the Main Thread (like below), the ContinueWith do not wait until completion of those actions, even if I ask to await them ?!? See order of execution below.

protected override async void UpdateDataSpeciliazed()
{
    _Data.Clear();
    Debug.WriteLine($"DaysPrestasService - UpdateDataSpeciliazed");

    await Device.InvokeOnMainThreadAsync(() => {
        Debug.WriteLine($"DaysPrestasService - Transferd to UI Thread");

        // Read and add DATA here

        Status = ModelStatus.Filled;
        Debug.WriteLine($"DaysPrestasService - Endof UI Thread");
    });

    Debug.WriteLine($"DaysPrestasService - UpdateDataSpeciliazed ended");
}

BaseModel<Data.DaysPrestasCard> - Launching Async Update
BaseModel<Data.DaysPrestasCard> - Launching Update Process
BaseModel<Data.DaysPrestasCard> - Update Process Lauchned
BaseModel<Data.DaysPrestasCard> - Launching error checking set up
DaysPrestasService - UpdateDataSpeciliazed
BaseModel<Data.DaysPrestasCard> - Checking ModelStatus (Updating)
BaseModel<Data.DaysPrestasCard> - UpdateDataAsync- ModelStatus not updated
DaysPrestasService - Transferd to UI Thread ---> DONE AFTER CHECK ?!?
DaysPrestasService - Endof UI Thread ---> DONE AFTER CHECK ?!?
DaysPrestasService - UpdateDataSpeciliazed ended ---> DONE AFTER CHECK ?!?

Can anybody tell me how to prevent ContinueWith to begin when execution in UpdateDataSpeciliazed jump to another thread ? It is strange for me because of the await before Device.InvokeOnMainThreadAsync

Thanks a lot !!!

Belight
  • 205
  • 2
  • 14

1 Answers1

0

That's because async void is not awaitable but if it was, you're anyway not awaiting it. Thus continuation runs before the method exit.

You may try sync-over-async call to update the UI:

protected override void UpdateDataSpeciliazed()
{
    _Data.Clear();
    Debug.WriteLine($"DaysPrestasService - UpdateDataSpeciliazed");

    Device.InvokeOnMainThreadAsync(() => {
        Debug.WriteLine($"DaysPrestasService - Transferd to UI Thread");

        // Read and add DATA here

        Status = ModelStatus.Filled;
        Debug.WriteLine($"DaysPrestasService - Endof UI Thread");
    }).Wait();

    Debug.WriteLine($"DaysPrestasService - UpdateDataSpeciliazed ended");
}

Continuation will works the only after the method is finished.

Or as alternative way: are you're able to change the signature of UpdateDataSpeciliazed() to async Task?

aepot
  • 4,558
  • 2
  • 12
  • 24
  • 1
    Thanks. That's the difference : https://stackoverflow.com/questions/13140523/await-vs-task-wait-deadlock – Belight Aug 23 '20 at 15:44
  • @Belight yes, there's an improtant difference. But you're runnung it on a separate Thread, not on the same. Thus `Wait()` here is safe thing. Finally the above suggestion is not the only and probably not the best way to solve. – aepot Aug 23 '20 at 15:46
  • I suppose in this case I can block the thread of UpdateDataSpeciliazed with .Wait() without slowndown as I know that is runs on a specific thread ? – Belight Aug 23 '20 at 15:48
  • 1
    Oups already answered .. Sorry – Belight Aug 23 '20 at 15:49