Home > Enterprise >  Prism: Closing Dialog Through Event
Prism: Closing Dialog Through Event

Time:09-21

I'm trying to build a simple dialog with a loading animation to show while a task is running. I use the Prism IDialogService and IEventAggregator However, I get a System.InvalidOperationException as the dialog with the animation pops up but never get's closed when the task is finished.

The Exception message is: The calling thread cannot access this object because a different thread owns it.

The dialog can be closed by clicking on it's X Button with no issues.

In non-async situations, I can open and close dialogs as I want, but I can't wrap my head around doing this async.

This is what I came up with so far, leading to the aforementioned Error.

WarehouseViewModel.cs

The Data is loaded and the dialog gets shown.

        private async void LoadData()
        {
            await WarehouseListLoad().ContinueWith(t => { _eventAggregator.GetEvent<LoadingFinishedEvent>().Publish(true); });
        }

        private async Task WarehouseListLoad()
        {
            _dialogService.ShowDialog("LoadingDialogView");
            List<Warehouse> warehouses = await Task.Run(() =>
            {
                List<Warehouse> list = _warehouseStore.GetAll();
                return list;
            });
        }

LoadingDialogViewModel.cs

Listen for the LoadingFinishedEvent and invoke RequestClose.


        public event Action<IDialogResult> RequestClose;

        public LoadingDialogViewModel(IEventAggregator eventAggregator)
        {
            eventAggregator.GetEvent<LoadingFinishedEvent>().Subscribe(close => CloseDialog(null));
        }

        protected virtual void CloseDialog(string parameter)
        {
            RaiseRequestClose(new DialogResult(ButtonResult.None));
        }

        public virtual void RaiseRequestClose(IDialogResult dialogResult)
        {
            try
            {
                RequestClose?.Invoke(dialogResult);
            }
            catch(System.InvalidOperationException ex)
            {
                Debug.WriteLine(ex.Message);
                //System.InvalidOperationException: The calling thread cannot access this object because a different thread owns it
            }
        }

CodePudding user response:

You either want to Subscribe on the UI-Thread

eventAggregator.GetEvent<LoadingFinishedEvent>().Subscribe(close => CloseDialog(null), ThreadOption.UIThread);

or use the Dispatcher to invoke RequestClose.

Application.Current.Dispatcher.Invoke( () => RequestClose?.Invoke(dialogresult) );

Or you drop Task.Run and make GetAll actually asynchronous...

  • Related