c#5.0中的新异步语言功能在很大程度上依赖于Task对象,许多示例表明在Task中运行某些代码的一种常见方法是通过Task.Run()启动它,它代表你的代码作为任务并在线程池线程上运行。
但是,我也读过一个不应该在线程池线程上启动长时间运行的代码,这引出了我的问题:是否仍然可以使用所有C#异步语言功能(例如Task,'await' ,“async”)在“常规”线程上而不是使用线程池?在这种情况下,如何获得代表在“常规”线程上运行的代码的Task对象?
作为关于不在线程池中运行长时间运行代码的规则的后续问题 - 这个规则是关于cpu密集的代码吗?如果你的代码运行很长时间(例如72小时)但是花费大部分时间做“await Task.Delay()”这样的事情怎么办呢?那么可以使用线程池线程,或者应该使用“常规”你的并发代码需要运行很长时间的所有情况下的线程?
答案 0 :(得分:3)
您可以通过自定义Task
在任意位置投放TaskScheduler
。
但是,如果你所做的只是await Task.Delay()
,你就不应该打扰
异步调用的全部目的是在等待某事发生时不要占用线程。
在等待Task.Delay()
时,根本没有运行任何线程。
如果您实际上长时间运行同步代码,则可以指定TaskCreationOptions.LongRunning
以强制它创建新线程。
答案 1 :(得分:3)
我也读过一个不应该在线程池线程上启动长时间运行的代码
线程池将正确响应长时间运行的代码,因此它不像不能那样做 - 它不是最有效的< / em>这样做的方式。
另请注意,Task.Delay
暗示“长跑”的相反 - 个人Task
实际上在await
处完成,并且不是线程池上的时间更长。当Task
完成时,将创建另一个Task.Delay
并将其排队到线程池。 Task
返回的Task.Run
(当您传递async
委托时)实际上是代表整个代表的“代理Task
”。
是否仍然可以在“常规”线程上使用所有C#异步语言功能(例如Task,'await','async')而不使用线程池?
在您的情况下,您不需要它,但 是可能的。我的AsyncEx library包含AsyncContextThread
类型,该类型公开了TaskFactory
属性,您可以使用该属性在该主题上启动Task
。
我正在使用Task.Run()
“并行”为所有实例提供服务
在您的情况下,您根本不需要Task.Run
或TaskFactory
。您可以轻松地并行执行此操作,而无需将工作明确地发送到线程池:
string[] instanceNames = ...;
var tasks = instanceNames.Select(ServiceInstanceAsync);
await Task.WhenAll(tasks);
private static async Task ServiceInstanceAsync(string name)
{
await DownloadAndProcessFileAsync();
await Task.Delay(15000);
await ExecuteSSHAsync();
}