我正在开发一个应用程序来监视某些任务(例如,如果某些服务/网站正在运行,数据库中的某些记录存在等)。由于大多数这些任务长期运行,我使用TPL
与async/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
,其回报值将不会被用于任何地方,我想不出我为什么需要它
我会很感激,如果有人可以澄清这些点
不知道是不是重复的,但可能是:http://stackoverflow.com/questions/12144077/async-await-when-to-return-a-task-vs-void –
使用'async void'唯一有意义的地方是当你需要在同步上下文中处理事件处理程序时 - 同步上下文使其安全,并且事件处理程序不能返回值。在其他地方使用'async Task' - 没有理由不这样做。您的代码看起来有点可疑 - 例如使用'Task.Factory.StartNew'而不是'Task.Run'并使用它来启动一个异步方法。为什么不使用任务'开始'返回来跟踪长时间运行的状态而不是你自己的(可能是线程不安全的)标志? – Luaan
@Luaan,我没有返回Task,因为我不需要调用代码中的Task对象(我正在跟踪其他方式的操作状态)。如果我改变它返回'Task'并保持呼叫,因为它是'o.Start()',我得到一个警告,建议在呼叫中加入'await',这是我根本不需要的。 –