Обработка ошибок от бизнес-уровня до пользовательского интерфейса - PullRequest
0 голосов
/ 12 декабря 2018

Я запускаю статическую функцию main () и запускаю app.Run () для запуска окна WPF.Сначала это модель представления с набором пользовательских элементов управления.Оттуда пользователь нажимает кнопку подключения, которая запускает Task.Run () в другом статическом классе.

Когда моя задача сталкивается с исключениями, они возвращаются к app.Run (), а не к кнопке подключения.Я предполагаю, что они сообщают вызывающему потоку не то место, где была запущена задача.Некоторые из ошибок, с которыми я могу справиться на уровне задач, но другие должны быть видны пользователю.

Поэтому мой вопрос: что будет хорошей практикой для передачи этих ошибок в пользовательский интерфейс?

Мой текущий асинхронный ....

   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 голосов
/ 12 декабря 2018

Короче говоря, ваши Исключения не соблюдаются (то есть вы запускаете задачи запуска и забывания).

Некоторые соображения:

  1. Есливы используете Task.Run(), затем используете Task.ContinueWith , есть много примеров того, как это сделать.Тем не менее, выгода для задач «забыть» и «забыть» (термин используется свободно) заключается в том, что вы можете проверить, не было ли исключение, вызванное методом вызова, и обработать его соответствующим образом.

  2. Выполните этот шагдалее и используйте async и await, где это возможно.Он заботится о продолжениях и обработке ошибок, освобождает пользовательский интерфейс и аккуратен практически во всех отношениях.

Примеры

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
   }
} 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...