Исключение RaiseCanExecuteChanged COM во время навигации?

Обновить

Загруженный образец проекта: https://github.com/subt13/BugSamples

Я воспроизвел ошибку, возникающую в приложении Windows 10 UAP, использующем инфраструктуру MVVMLight.

Я получаю приведенную ниже ошибку во время навигации, когда ЦП находится под большой нагрузкой (~ 20-25%) и страница «тяжелая» (большие изображения, много элементов управления и т. д. и т. д.)

в System.Runtime.InteropServices.WindowsRuntime.ICommandAdapterHelpers.‹>c__DisplayClass2.b__3(отправитель объекта, EventArgs e) в System.EventHandler.Invoke(отправитель объекта, EventArgs e) в GalaSoft.MvvmLight.Command.RelayCommand.RaiseCanExecuteChanged() в RaiseExecuteChangeRepo .ViewModel.MainViewModel.d__17.MoveNext()

В примере ошибка возникает 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;
    }

Во время навигации не происходит ничего особенного, кроме того, что вызывается команда, связанная с ExecuteLoadDataCommandAsync(), для загрузки данных.

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

Чтобы воспроизвести, просто быстро переключитесь с одной страницы на другую в течение нескольких секунд, а затем просто подождите. Через некоторое время будет возбуждено исключение.


person O.O    schedule 16.09.2015    source источник
comment
E_FAIL — это всего лишь учительская оценка качества отчетов об ошибках в WinRT. Совершенно бесполезно диагностировать основную проблему. Это может быть проблемой многопоточности, всегда ненулевой шанс для этого в асинхронном/ожидающем коде. Но опять же, это может быть что угодно. Вам придется найти надежный сценарий воспроизведения, не планируйте ничего делать на следующей неделе.   -  person Hans Passant    schedule 17.09.2015
comment
@HansPassant - Ага, работаю над этим.   -  person O.O    schedule 17.09.2015
comment
Я предполагаю, что это вызвано быстрым переключением с одной страницы на другую в течение нескольких секунд, а затем просто ожиданием. - ваши операции async все еще выполняются, и когда они завершаются, они пытаются взаимодействовать с деревом XAML, которое больше не активно. Чтобы исправить это, убедитесь, что вы все еще активны на странице, прежде чем создавать события.   -  person Peter Torr - MSFT    schedule 19.09.2015
comment
Установив для DataContext значение null при выходе с главной страницы (переопределяя OnNavigatedFrom(NavigationEventArgs)). Мне удалось исправить исключение COM из метода RaiseCanExecuteChanged(), НО теперь я получаю еще одно исключение E_FAIL откуда-то еще. Я не знаю, как это применимо к вашему реальному приложению, но вам, возможно, придется отменить загрузку при выходе со страницы или, возможно, использовать кеш, чтобы избежать перезагрузки данных каждый раз.   -  person Vincent    schedule 23.09.2015
comment
Я тоже подозреваю, что это проблема повторного входа. Вы должны защитить ExecuteLoadDataCommandAsync от повторного входа и добавить некоторую логику отмены (чтобы RaiseCanExecuteChanged не запускался избыточно). Есть много способов сделать это, некоторые обсуждаются здесь.   -  person noseratio    schedule 24.09.2015
comment
@O.O Вы когда-нибудь находили причину? У меня похожая проблема, я не понимаю.   -  person Amenti    schedule 26.04.2016
comment
@Amenti - смотри мой ответ.   -  person O.O    schedule 26.04.2016


Ответы (1)


В итоге я решил свою проблему, добавив следующее событие в код позади.

protected override void OnNavigatedFrom(NavigationEventArgs e)
{
    this.DataContext = null;
    base.OnNavigatedFrom(e);
}
person O.O    schedule 26.04.2016