2016-08-17 33 views
2

我正在开发一个应用程序来监视某些任务(例如,如果某些服务/网站正在运行,数据库中的某些记录存在等)。由于大多数这些任务长期运行,我使用TPLasync/await替代异步void

我对所有这些任务的基类:

public abstract class LongRunningOperation 
{ 
    // .. some props... 

    internal async void Start() 
    { 
     try 
     { 
      this.Status = OperationStatus.Started; 
      await this.DoStart(); 
      this.Status = OperationStatus.Finished; 
     } 
     catch (Exception e) 
     { 
      this.Status = OperationStatus.Error; 
      this.Message = e.ToString(); 
     } 
    } 

    protected abstract Task DoStart(); 
} 

和方法,启动这些任务看起来是这样的:

public static LongRunningOperation[] LaunchOperations() 
{ 
    LongRunningOperation[] operations = GetAllLongRunningOperations(); 
    foreach (var o in operations) 
     Task.Factory.StartNew(() => { o.Start(); }); 
    return operations; 
} 

通过此方法返回的数组用于监控所有LongRunningOperation并记录统计信息。目前我有一个控制台应用程序,其中有一个while (true)循环,用于输出屏幕上每个操作(每秒刷新一次)的统计信息(名称,状态,当前运行时),直到所有操作完成。

困扰我的事情是async void方法。我读过,这是不好的做法使用async void方法,但:

  • 我想不通,他们可能会在我的情况
  • 做什么伤害如果我改变Start方法返回Task,其回报值将不会被用于任何地方,我想不出我为什么需要它

我会很感激,如果有人可以澄清这些点

+1

不知道是不是重复的,但可能是:http://stackoverflow.com/questions/12144077/async-await-when-to-return-a-task-vs-void –

+2

使用'async void'唯一有意义的地方是当你需要在同步上下文中处理事件处理程序时 - 同步上下文使其安全,并且事件处理程序不能返回值。在其他地方使用'async Task' - 没有理由不这样做。您的代码看起来有点可疑 - 例如使用'Task.Factory.StartNew'而不是'Task.Run'并使用它来启动一个异步方法。为什么不使用任务'开始'返回来跟踪长时间运行的状态而不是你自己的(可能是线程不安全的)标志? – Luaan

+0

@Luaan,我没有返回Task,因为我不需要调用代码中的Task对象(我正在跟踪其他方式的操作状态)。如果我改变它返回'Task'并保持呼叫,因为它是'o.Start()',我得到一个警告,建议在呼叫中加入'await',这是我根本不需要的。 –

回答

5

异步void方法是一种“发射后不管”的操作。您无法等待任何结果,并且无法知道操作何时完成以及是否成功。

基本上,如果您确定无需知道操作何时完成以及操作执行是否成功(例如编写日志),则应该使用void。

使用返回Task的异步方法,调用方可以等待操作完成,并处理在执行操作期间发生的异常。总之,如果你不需要结果,异步Task稍微好一些,因为你可以等待它,以及处理异常和处理任务排序。

+1

即使为了写日志类型的操作,你也不应该使用void return作为异步方法,它是它们的唯一事件,这是特殊情况 –

+1

@MrinalKamboj,“即使为了写日志类型的操作,你也不应该使用void return” - 为什么不? –

+0

@Andre Borges请检查上面J Steen提供的链接,该链接将详细回答您的问题。即使你想开火并忘记,你不想做的事情是,不能控制那个通话的失败,从而影响你当前的通话 –

0

以下是您发布的两个重要问题

我想不通,他们可能会在我的情况做有什么危害

看看下面的链接,它已经被张贴在以上,真正回答评论包含该点你都在问:

async/await - when to return a Task vs void?

PLE ase明白void返回可用,为事件提供兼容性,这些事件具有void返回值,并且它们的异常由Synchronization context/Ui线程处理,否则对于其他任何调用,为什么我们总是要依靠最小返回一个Task类型,以避免通话中的例外情况,在我们没有任何控制App Domain unhandled exception的情况下终止进程,因为这会传播。你的过程将不会未经您的知识或信息被杀,是控制任何一种伤害到你的系统,甚至连发的时候,忘记

如果我改变Start方法返回的任务,它的返回大办值将不会被用于任何地方,我想不出我为什么需要它

除了上述涉及到了未处理的异常控制中提到的一点,也可以考虑这种方式,通过返回Task,你有一个选择如果需要,甚至可以打电话给Async,因为只有Task可以是awaited,而不是空白,这迫使t他主叫方只Synchronous,这将是为Web ProjectsWeb API一个重要的要求,这可能需要一个服务是一个Asynchronous实施