从业务层到UI的错误处理

时间:2018-12-12 02:40:10

标签: 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;
        }
    }

1 个答案:

答案 0 :(得分:1)

简而言之,您的 Exception 是未被观察到的(也就是说,您正在起火而忘记了任务)。

一些注意事项:

  1. 如果您使用的是Task.Run(),然后使用Task.ContinueWith,则有许多示例。但是,解雇任务的好处(宽松使用的术语)是,您可以检查调用方法是否抛出异常并进行相应处理。

  2. 更进一步,请使用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
   }
}