c# - 从业务层到UI的错误处理

标签 c# wpf mvvm error-handling

我正在运行静态main()并执行app.Run()来启动WPF窗口。基本上,它首先是带有大量用户控件的viewmodel。用户从此处单击连接按钮,该按钮将在另一个静态类中启动Task.Run()。

当我的任务遇到异常时,它们会冒泡回到app.Run()而不是连接按钮。我猜他们正在向调用线程报告而不是从任务开始的位置。我可以在任务级别处理一些错误,但其他错误则需要用户看到。

所以我的问题是,将这些错误发送到UI的良好做法是什么?

我目前的异步...

   private static async void MainMountLoopAsync()
    {
        try
        {
            if (_ctsMount == null) _ctsMount = new CancellationTokenSource();
            var ct = _ctsMount.Token;
            var task =  Task.Run(() =>
            {
                while (!ct.IsCancellationRequested)
                {
                    MoveAxes();
                }
            }, ct);
            await task;
            task.Wait(ct);
            AbortSlew();
            MainLoopRunning = false;
            SkySystem.ConnectSerial = false;
            IsSkyConnected = SkySystem.ConnectSerial;
        }
        catch (OperationCanceledException)
        {
            MainLoopRunning = false;
            MonitorLog.LogToMonitor(MonitorDevice.Telescope, MonitorCategory.Server, MonitorType.Information,
                $"{MethodBase.GetCurrentMethod().Name}, {Thread.CurrentThread.ManagedThreadId}, Cancel Main Loop Task Requested");
        }
        catch (Exception ex)
        {
            MainLoopRunning = false;
            MonitorLog.LogToMonitor(MonitorDevice.Telescope, MonitorCategory.Server, MonitorType.Error,
                $"{MethodBase.GetCurrentMethod().Name}, {Thread.CurrentThread.ManagedThreadId}, Message:{ex.Message} Stack:{ex.StackTrace}");
            AlertState = true;
            throw;
        }
    }

最佳答案

简而言之,您的异常是无法观察到的(也就是说,您正在起火而忘记了任务)。

一些注意事项:

  • 如果您使用的是Task.Run(),请使用Task.ContinueWith,其中有许多示例。但是,解雇任务(宽松使用的术语)的好处是,您可以检查调用方法是否抛出异常并进行相应处理。
  • 进一步执行此步骤,并在可能的情况下使用asyncawait。它负责连续性和错误处理,释放了UI,几乎在各个方面都更加整洁。

  • 示例
    public void ContinueWithOperation()  
    {  
       Task<string> t = Task.Run(() => LongRunningOperation("Continuewith", 500));  
       t.ContinueWith((t1) =>  
       {  
          // check t1 for errors here
          Console.WriteLine(t1.Result);  
       });  
    }  
    
    
    //Fake async! very smelly
    public async Task AsyncOperation()  
    {
       try
       {
          string t = await Task.Run(() => LongRunningOperation("AsyncOperation", 1000));  
          Console.WriteLine(t);  
       }
       catch (Exception e)
       {
           // check for errors here
       }
    } 
    
    // Ideally 
    public async Task OperationAsync()  
    {
       try
       {
          string t = await LongRunningOperationAsync("AsyncOperation", 1000);  
          Console.WriteLine(t);  
       }
       catch (Exception e)
       {
           // check for errors here
       }
    } 
    

    关于c# - 从业务层到UI的错误处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53735304/

    相关文章:

    c# - 在 ListView 中的网格中的标签中绑定(bind)到 ContextMenu 中的 ICommand 不起作用

    c# - 如何让 DataGridTemplateColumn 标题绑定(bind)工作?

    c# - 序列化是否最适合通过套接字发送数据?

    c# - C#调用存储过程

    wpf - 样式按钮图像仅适用于最后一项

    wpf - 如何在 WPF 中设置网格列定义的样式

    c# - Xamarin.Forms Navigation.PushAsync 在 ContentView 中不起作用

    c# - 表单关闭对话框结果出现在所有表单中

    c# - AutoGenerateColumn e.cancel 是否会影响 Table.Column.Count?

    wpf - UserControl 根据数据类型更新图像