首页 > 解决方案 > 使用 Task.ContinueWith 时在哪里捕获异常?

问题描述

我想用 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.ContinueWith”周围使用一个 try-catch 块?

标签: exceptionasync-await

解决方案


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

正确的答案是“不要使用ContinueWith”。对于异步代码,可以await改用;对于这样的同步代码,你可以什么都不用:

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

但是,像这样包装方法体Task.Run是一种反模式;最好保持方法同步并让调用者使用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


推荐阅读