【问题标题】:TaskFactory handle exceptionsTaskFactory 处理异常
【发布时间】:2016-10-18 23:32:25
【问题描述】:

如何在不阻塞 UI 线程的情况下轻松处理正在运行的任务中发生的所有异常。

我找到了很多不同的解决方案,但它们都涉及wait() 函数,这会阻塞整个程序。

任务正在异步运行,因此它应该只向 UI 线程发送一条消息,说明它有一个异常,以便 UI 线程可以处理它。 (也许是我可以参与的事件?)

这是我现在拥有的阻止 UI 线程的代码:

var task = Task.Factory.StartNew(() =>
{
    if (_proxy != null)
    {
        _gpsdService.SetProxy(_proxy.Address, _proxy.Port);
        if (_proxy.IsProxyAuthManual)
        {
            _gpsdService.SetProxyAuthentication(_proxy.Username,
                StringEncryption.DecryptString(_proxy.EncryptedPassword, _encryptionKey).ToString());
        }
    }

    _gpsdService.OnLocationChanged += GpsdServiceOnOnLocationChanged;
    _gpsdService.StartService();
});
try
{
    task.Wait();
}
catch (AggregateException ex)
{
    if (ex.InnerException != null)
    {
        throw ex.InnerException;
    }
    throw;
}

【问题讨论】:

  • 您使用的是哪个 c# 版本?你可以等待任务吗?你需要 C# 5。然后你可以很容易地使用 try catch
  • task.ContinueWith(task => {... }, TaskContinuationOptions.OnlyOnFaulted);
  • @Sebi 我们现在使用的是 .NET 4.5.2 版。
  • @DmitryBychenko 我真的可以使用这个将异常进一步抛出三个吗?因为我想把它扔给实际处理异常的 ViewModel :)
  • @Ghosttje:看起来ViewModel 应该提供一个用于继续的例程(例如,如果抛出任何异常这是一个应该响应它的Model):task.ContinueWith(task => SomeRoutine(task.Exception), TaskContinuationOptions.OnlyOnFaulted);。它看起来不像顺序代码那么容易。如果模型的运行,比如 5 Tasks 和 3d with 4th 失败了怎么办。我们应该抛出 3d 任务的异常,还是第 4 个,将它们组合起来(按什么顺序)?

标签: c# multithreading taskfactory


【解决方案1】:

您不应该使用Task.Factory.StartNew(改用Task.Run)。另外,不要使用ContinueWith(改用await)。

同时应用这两个准则:

try
{
  await Task.Run(() =>
  {
    if (_proxy != null)
    {
      _gpsdService.SetProxy(_proxy.Address, _proxy.Port);
      if (_proxy.IsProxyAuthManual)
      {
        _gpsdService.SetProxyAuthentication(_proxy.Username,
            StringEncryption.DecryptString(_proxy.EncryptedPassword, _encryptionKey).ToString());
      }
    }

    _gpsdService.OnLocationChanged += GpsdServiceOnOnLocationChanged;
    _gpsdService.StartService();
  });
}
catch (Exception ex)
{
  // You're back on the UI thread here
  ... // handle exception
}

【讨论】:

    【解决方案2】:

    您可以订阅TaskScheduler.UnobservedTaskException事件

    【讨论】:

      【解决方案3】:

      您使用的是 .Net 版本 4.5.2,因此您的语言版本应该是 c# 5。因此您可以执行以下操作:

      try
      {
       Task t1 = await Task.Factory.StartNew(() => {
      
        //Do you stuff which may cause exception
       })
      }
      catch ()
      {}
      

      await 关键字导致您必须使用异步标记您的方法。但它不会阻塞并且非常直观。如果这不起作用,请使用 Dmitry Bychenko 的想法:

      Task t1 = await Task.Factory.StartNew(() => {
      
            //Do you stuff which may cause exception
           }).ContinueWith(t=>ShowError(), TaskContinuationOptions.OnlyOnFaulted);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多