【问题标题】:Prism: Closing Dialog Through EventPrism:通过事件关闭对话
【发布时间】:2021-11-14 04:07:48
【问题描述】:

我正在尝试构建一个带有加载动画的简单对话框,以便在任务运行时显示。 我使用棱镜IDialogServiceIEventAggregator 但是,我得到一个System.InvalidOperationException,因为带有动画的对话框会弹出,但任务完成后永远不会关闭。

异常消息是:调用线程无法访问此对象,因为另一个线程拥有它。

可以通过单击它的 X 按钮来关闭对话框,没有任何问题。

在非异步情况下,我可以根据需要打开和关闭对话框,但我无法专心做这种异步。

这是我迄今为止想出的,导致上述错误。

WarehouseViewModel.cs

加载数据并显示对话框。

        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

监听 LoadingFinishedEvent 并调用 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
            }
        }

【问题讨论】:

  • 你为什么在这里混合async/awaitContinueWith?这是为了混淆代码吗?

标签: c# wpf prism


【解决方案1】:

您要么想在 UI 线程上Subscribe

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

或使用Dispatcher 调用RequestClose

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

或者你放弃Task.Run 并使GetAll 实际上是异步的......

【讨论】:

  • 我不知道我是如何在documentation 中读到的。非常感谢!
猜你喜欢
  • 2015-08-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多