【发布时间】:2014-07-13 03:28:38
【问题描述】:
有好几次,我发现自己为轮询循环之类的事情编写了长时间运行的异步方法。这些方法可能看起来像这样:
private async Task PollLoop()
{
while (this.KeepPolling)
{
var response = await someHttpClient.GetAsync(...).ConfigureAwait(false);
var content = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
// do something with content
await Task.Delay(timeBetweenPolls).ConfigureAwait(false);
}
}
为此目的使用 async 的目的是我们不需要专用的轮询线程,但(对我而言)逻辑比直接使用计时器之类的东西更容易理解(另外,无需担心重入)。
我的问题是,从同步上下文启动此类循环的首选方法是什么?我能想到至少两种方法:
var pollingTask = Task.Run(async () => await this.PollLoop());
// or
var pollingTask = this.PollLoop();
在任何一种情况下,我都可以使用 ContinueWith() 来响应异常。我对这两种方法之间区别的主要理解是,第一种方法最初将在线程池线程上开始循环,而第二种方法将在当前线程上运行,直到第一次等待。这是真的?是否有其他需要考虑或尝试更好的方法?
【问题讨论】:
-
在第一个中我看到了 3 个任务.. 1)
Task.Run2) 因为await(由编译器生成) 3) PollLoop 本身。另一方面,第二个只有 1 个任务。 -
如果将第一个任务版本减少到2个,可以更好地看到答案:
Task.Run(() => this.PollLoop().Wait()) -
如果这是一个服务器端代码,你就不需要
Task.Run。 -
但是如果这个任务有很多代码并且是从windows服务启动的,服务启动会等待await...而且服务运行可能需要很长时间..所以a诀窍就是把
await Task.Delay(10);放在开头
标签: c# task-parallel-library async-await