C# 从后台操作导航

C# 从后台操作导航,c#,wpf,prism,C#,Wpf,Prism,我的应用程序中有一个显示的页面,我想执行一个潜在的长时间运行的后台操作。此操作正在进行时,应显示另一个视图,完成后,应将该区域导航回其以前的视图。如果出现任何问题,导航应该转到其他视图 为了说明这一点,假设我有一些类,并在其构造函数中设置一个ICommand: SomeAction = new DelegateCommand(() => { _regionManager.RequestNavigate("MyTarget", nameof(SomeProgressPage));

我的应用程序中有一个显示的页面,我想执行一个潜在的长时间运行的后台操作。此操作正在进行时,应显示另一个视图,完成后,应将该区域导航回其以前的视图。如果出现任何问题,导航应该转到其他视图

为了说明这一点,假设我有一些类,并在其构造函数中设置一个ICommand:

SomeAction = new DelegateCommand(() =>
{
    _regionManager.RequestNavigate("MyTarget", nameof(SomeProgressPage));

    Task.Run(() =>
    {
        DoSomeWork();
    });
});
任务本身与潜在的长期运行相关;一旦完成,它应该导航到一个有条件的目的地

private void SomeWork()
{
    try
    {
        // Do Work
        // ...

        // Return when done.
        _regionManager.RequestNavigate("MyTarget", nameof(SomePage));
    }
    catch
    {
        _regionManager.RequestNavigate("MyTarget", nameof(SomeErrorPage));
    }
}
虽然我可以在调试中逐步完成这一过程,并且不会在调试过程中遇到任何错误,但当从另一个线程调用RequestNavigation时,它似乎没有任何效果,也不会引发异常。我确实导航到“SomeProgressPage”,任务确实在运行,并且根据其结果,可以跟踪执行到RequestNavigation,然后什么也不做

我还尝试通过以下事件执行此导航:

eventAggregator.GetEvent<NavigationRequestEvent>().Subscribe(x =>
{
    regionManager.RequestNavigate(x.Target, x.Destination, x.Parameters);

}, ThreadOption.UIThread);
eventAggregator.GetEvent().Subscribe(x=>
{
regionManager.RequestNavigate(x.Target,x.Destination,x.Parameters);
},ThreadOption.UIThread);
在这种情况下,发布事件时甚至不会调用订阅服务器


我在谷歌上找不到任何可靠的资源来处理这个问题,也没有通过Prism连接到源代码和调试;在使用Prism时,如何最好地实现这类功能

问题是,任务AggregatedException处理程序会吞没在未等待的任务中抛出的异常。通过检查task.Exception属性,可以访问任务引发的异常。您还可以执行以下操作:

        Task.Run(() =>
        {
            //DoSomeWork();
        })
        .ContinueWith((t) =>
        {
            // Return when done.
            _regionManager.RequestNavigate("MyTarget", nameof(SomePage));
        })
        .ContinueWith((t) =>
        {
            _regionManager.RequestNavigate("MyTarget", nameof(SomeErrorPage));
        }, TaskContinuationOptions.OnlyOnFaulted);

第二个ContinueWith仅在任务出现故障时启动(意味着任务引发了异常)。

如果要从另一个线程打开新窗口,则需要调用当前调度程序

    private void SomeWork()
            {
                try
                {
                    // Do Work
                    // ...

                    // Return when done.
                   App.Current.Dispatcher.Invoke((Action)delegate
                    {

                    _regionManager.RequestNavigate("MyTarget", nameof(SomePage));

                    });
                }
                catch
                {
                  App.Current.Dispatcher.Invoke((Action)delegate
                    {

                    _regionManager.RequestNavigate("MyTarget", nameof(SomeErrorPage));

                    });
                }        
        }