【发布时间】:2013-12-14 16:22:52
【问题描述】:
我有一个用 C# 编写的 Windows 服务,它会定期触发后台作业。通常,在任何给定时间,数十个 I/O 密集型任务(下载大文件等)并行运行。该服务在相对繁忙的 Web 服务器上运行(目前是必需的),我认为尽可能使用异步 API 在线程保护方面会受益匪浅。
大部分工作已经完成。所有作业现在都是完全异步的(利用 HttpClient 等),主作业循环也是如此(大量的 Task.Delay)。剩下的就是弄清楚如何从服务的 OnStart 正确和安全地启动主循环。本质上,这是一个备受警告的从同步调用异步的困境。以下是我到目前为止的内容(非常简化)。
在 Program.cs 中:
static void Main(string[] args) {
TaskScheduler.UnobservedTaskException += (sender, e) => {
// log & alert!
e.SetObserved();
};
ServiceBase.Run(new MyService());
}
在 MyService.cs 中:
protected override void OnStart(string[] args) {
_scheduler.StartLoopAsync(); // fire and forget! will this get me into trouble?
}
我担心的是对StartLoopAsync 的调用。我不能简单地在返回的任务上Wait(),因为 OnStart 需要相对较快地返回。 (作业循环需要在单独的线程上运行。)我想到了几个想法:
- 我是否通过将处理程序放在 Main 中来很好地覆盖未观察到的异常?
- 使用 Task.Run 有什么好处吗,比如
Task.Run(() => _scheduler.StartLoopAsync().Wait());? - 在这里拨打
_scheduler.StartLoopAsync().ConfigureAwait(false)有什么好处吗? (我对此表示怀疑,因为这里没有await。) - 在这种情况下使用Stephen Cleary's AsyncContextThread 会有什么好处吗?我还没有看到任何使用它的例子,而且由于我正在启动一个无限循环,我不知道同步备份到某些上下文在这里甚至是相关的。
【问题讨论】:
-
下周我会写一个
AsyncContextThread的例子。 -
所以我不再纠缠你了? ;) 不用担心,我很期待,再次感谢您的帮助!
-
没问题。实际上,我只是从很久以前就看到了您对 CodePlex 的评论,出于某种原因,我没有收到通知...
-
嘿@StephenCleary,您有没有机会向我们介绍如何在Windows 服务中使用AsyncContextThread 的示例?我不清楚是应该从 OnStart() 还是从 Main() 调用它。
-
@N1njaB0b: 是的,我从来没有抽空写下来……它还在我的待办事项清单上……你应该从
OnStart调用它,然后在@ 中加入它987654331@.
标签: c# asynchronous windows-services async-await