c# – Task.Run与直接异步调用,用于启动长时间运行的异步方法
有好几次,我发现自己编写了长时间运行的异步方法,比如轮询循环.这些方法可能如下所示:
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); } } 为此目的使用异步的目的是我们不需要专用的轮询线程,但逻辑(对我而言)比直接使用像计时器这样的东西更容易理解(也就是说,不需要担心重入). 我的问题是,从同步上下文启动这样一个循环的首选方法是什么?我能想到至少两种方法: var pollingTask = Task.Run(async () => await this.PollLoop()); // or var pollingTask = this.PollLoop(); 在任何一种情况下,我都可以使用ContinueWith()来响应异常.我对这两种方法之间差异的主要理解是,第一个将首先在线程池线程上开始循环,而第二个将在当前线程上运行,直到第一个等待.这是真的?还有其他需要考虑的事项或更好的方法吗? 解决方法
是.异步方法在第一次等待尚未完成的等待时将其任务返回给其调用者. 按照惯例,大多数异步方法返回非常快.你也可以,因为等待一些HttpClient.GetAsync将很快到达. 将这个异步方法的开头移到线程池上是没有意义的.它增加了开销,几乎没有延迟.它当然无助于吞吐量或扩展行为. 在这里使用异步lambda(Task.Run(async()=> await this.PollLoop()))尤其无用.它只是将PollLoop返回的任务包含在另一层任务中.最好说Task.Run(()=> this.PollLoop()). (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |