RaiseCanExecuteChanged COM Exception during Navigation?
Asked Answered
H

1

9

Update

Uploaded sample project: https://github.com/subt13/BugSamples

I have reproduced an error that has been occurring in a Windows 10 UAP application that utilizes the MVVMLight framework.

I receive the error below during navigation while the CPU is under heavy load (~20-25%) and the page is "heavy" (large images, lots of controls, etc., etc.)

at System.Runtime.InteropServices.WindowsRuntime.ICommandAdapterHelpers.<>c__DisplayClass2.b__3(Object sender, EventArgs e) at System.EventHandler.Invoke(Object sender, EventArgs e) at GalaSoft.MvvmLight.Command.RelayCommand.RaiseCanExecuteChanged() at RaiseExecuteChangeRepo.ViewModel.MainViewModel.d__17.MoveNext()

In the sample, the error occurs on RaiseCanExecuteChanged();

    private async void ExecuteLoadDataCommandAsync()
    {
        // cause the app to slow done.
        var data = await Task.Run(() => GetData()); 

        if (data != null)
        {
            this.Data.Clear();

            foreach (var item in data)
            {
                this.Data.Add(new AnotherVM(item));
            }
        }

        // have the select job command rerun its condition
        this.SelectCommand.RaiseCanExecuteChanged();
    }

    // slow down the page
    public List<DataItem> GetData()
    {
        var myList = new List<DataItem>();
        for (int i = 0; i < 100000; ++i)
        {
            myList.Add(new DataItem("Welcome to MVVM Light"));

        }

        return myList;
    }

Nothing special is happening during navigation other than the command associated with ExecuteLoadDataCommandAsync() is getting called to load data.

<Core:EventTriggerBehavior EventName="Loaded">
    <Core:InvokeCommandAction Command="{Binding LoadDataCommand}">
   </Core:InvokeCommandAction>
</Core:EventTriggerBehavior>

To reproduce, simply toggle from one page to the other rapidly for a few seconds and then just wait. After not too long the exception will be raised.

His answered 16/9, 2015 at 19:33 Comment(7)
E_FAIL is only a teacher's grade for the quality of the error reporting in WinRT. It is completely useless to diagnose the underlying problem. It might be a threading problem, always non-zero odds for it in async/await code. But then again it could be anything. You'll have to find a reliable repro scenario, don't plan to do accomplish anything for the next week.Ericerica
@HansPassant - Yup, working on that.His
My guess is that it is caused by "toggle from one page to the other rapidly for a few seconds and then just wait." - your async operations are still running, and when they complete they try to interact with a XAML tree that is no longer active. To fix, make sure you're still the active page before raising the events.Meyerbeer
By setting the DataContext to null when leaving the main page (overriding OnNavigatedFrom(NavigationEventArgs)). I've been able to fix the COM Exception from the RaiseCanExecuteChanged() method BUT, I'm now getting another E_FAIL exception from somewhere else. I do not know how it apply to your real application but you might have to cancel the load when leaving the page or maybe use a cache to avoid reloading everytime the data.Daydream
I too suspect it's a re-entrancy issue. You should guard ExecuteLoadDataCommandAsync from re-entrancy and add some cancellation logic (so RaiseCanExecuteChanged wouldn't be fired redundantly). There're many ways of doing that, some are discussed here.Romaic
@His Did you ever find the cause? I have a similar problem I don't understand.Jury
@Jury - see my answer.His
H
1

I ended up fixing my issue by adding the following event to the code behind.

protected override void OnNavigatedFrom(NavigationEventArgs e)
{
    this.DataContext = null;
    base.OnNavigatedFrom(e);
}
His answered 26/4, 2016 at 19:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.