使用Task.ContinueWith时在哪里捕获异常?

时间:2019-03-14 10:23:27

标签: exception async-await

我想使用Task创建一个异步方法,该方法创建一个文件并立即继续执行下一个任务,该任务将创建的文件上传到云中。 这是此方法的外观:

public async TaskCreateAndUploadAsync()
{
     await Task.Run(() =>
        {
            try
            {                 
                var _writeFile = new WriteFile(...);
                _writeFile.DoWork();
            }
            catch (Exception e)
            {
                //Log..
            }
        }).ContinueWith((result) =>
        {
        if (!result.IsFaulted)
            {
            try
            {
               storage.UploadCreatedObject(...);
            }
            catch (Exception e)
            {
                //Log..
            }
          }
        });
}

我的问题是:我如何分别捕获每个Task中的异常的方式还是应该在整个“ Task..Task.ContinueWith”周围使用一个try-catch块?

1 个答案:

答案 0 :(得分:1)

  

使用Task.ContinueWith时在哪里捕获异常?

正确的答案是“不要使用ContinueWith”。对于异步代码,可以使用await来代替;对于这样的同步代码,您什么也不能使用:

public async TaskCreateAndUploadAsync()
{
  await Task.Run(async () =>
  {
    try
    {                 
      var _writeFile = new WriteFile(...);
      _writeFile.DoWork();
      storage.UploadCreatedObject(...);
    }
    catch (Exception e)
    {
      //Log..
    }
  });
}

但是,wrapping a method body in Task.Run like this is an antipattern;最好使该方法保持同步并让调用方使用Task.Run

public void TaskCreateAndUpload()
{
  try
  {                 
    var _writeFile = new WriteFile(...);
    _writeFile.DoWork();
    storage.UploadCreatedObject(...);
  }
  catch (Exception e)
  {
    //Log..
  }
}

在您的方法名称中,听起来有些应该是异步的。 I / O本质上是异步的。因此,如果您具有真正的异步I / O(即,不使用Task.Run进行伪异步),那么生成的方法可能如下所示:

public async Task TaskCreateAndUploadAsync()
{
  try
  {                 
    var _writeFile = new WriteFile(...);
    await _writeFile.DoWorkAsync();
    await storage.UploadCreatedObjectAsync(...);
  }
  catch (Exception e)
  {
    //Log..
  }
}

请注意,在最后一个示例中,使用await代替了ContiueWith