加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 未处理的异步异常

发布时间:2020-12-15 20:57:04 所属栏目:百科 来源:网络整理
导读:避免异步空闲的原因,是否可以从调用代码中捕获以下错误? private static Action ErrorAction{ get { return async () = { await Task.Delay(0); throw new NotImplementedException(); }; }} 例如,在以下两个中我想收集抛出的异常,但两个测试都失败了: [Te
避免异步空闲的原因,是否可以从调用代码中捕获以下错误?

private static Action ErrorAction
{
  get
  {
    return async () =>
    {
      await Task.Delay(0);
      throw new NotImplementedException();
    };
  }
}

例如,在以下两个中我想收集抛出的异常,但两个测试都失败了:

[Test]
public void SelfContainedExampleTryCatch()
{
  List<Exception> errors = new List<Exception>();
  try
  {
     ErrorAction();
  }
  catch (Exception ex)
  {
    errors.Add(ex);
  }
  errors.Count().Should().Be(1);
}

[Test]
public void SelfContainedExampleContinueWith()
{
  List<Exception> errors = new List<Exception>();
  var task = Task.Factory.StartNew(ErrorAction);
  task.ContinueWith(t =>
                {
                    errors.Add(t.Exception);
                },TaskContinuationOptions.OnlyOnFaulted);
  task.Wait();

  errors.Count().Should().Be(1);
}

我知道我可以使用带有异步任务签名的方法;但具体来说,它是我需要处理的Action可分配代理异步代码示例,并且在全局级别捕获是不切实际的.如果可能的话,同步和异步动作共同的解决方案将是理想的.

希望有一个我错过的简单解决方案,但到目前为止,我只是走了许多死胡同并且(可能不正确)得出结论它是不可能的.任何帮助(或浪费时间)将不胜感激!

解决方法

在某些情况下,框架要求您使用异步void,有时您真的不愿意(例如,ICommand.Execute).在这些情况下,我通常建议引入一个与await兼容的API,并使你的异步void方法非常简单的包装器:

static Func<Task> ErrorActionAsync
{
  get
  {
    return async () =>
    {
      await Task.Yield();
      throw new NotImplementedException();
    };
  }
}

private static Action ErrorAction
{
  get
  {
    return async () => { await ErrorActionAsync(); }
  }
}

(在旁注中,我更改了等待Task.Delay(0)以等待Task.Yield(),因为等待Task.Delay(0)是noop).

然后,您可以在单元测试中使用ErrorActionAsync而不是ErrorAction.这种方法确实意味着您将拥有少量未经测试的代码(异步void包装器 – ErrorAction).

但是,如果您希望将ErrorAction保持原样,并且它可以是同步的或异步的,那么还有另一种可能性.我写了一个你可以这样使用的AsyncContext type:

[Test]
public void SelfContainedExampleTryCatch()
{
  List<Exception> errors = new List<Exception>();
  try
  {
    AsyncContext.Run(() => ErrorAction());
  }
  catch (Exception ex)
  {
    errors.Add(ex);
  }
  errors.Count().Should().Be(1);
}

AsyncContext.Run将阻塞,直到async void方法完成,并将从异步void方法捕获异常并直接引发它们.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读