让我们假设我们有一个I/O绑定方法(例如进行DB调用的方法)。此方法既可以同步运行,也可以异步运行。那是,
然后,当我们以如下所示的不同方式执行该方法时,在资源利用率方面的性能差异是什么?
发布于 2013-07-02 19:14:45
var task = Task.Factory.StartNew(() => { IOMethod(); });
task.Wait();这将在IOMethod()执行时阻塞线程池线程,还会因为Wait()而阻塞当前线程。阻塞线程总数: 2。
var task = Task.Factory.FromAsync(BeginIOMethod, EndIOMethod, ... );
task.Wait();这将(很可能)在不使用线程的情况下异步执行操作,但由于Wait(),它将阻塞当前线程。阻塞线程总数: 1。
IOMethod();这将在IOMethod()执行时阻塞当前线程。阻塞线程总数: 1。
如果您需要阻止当前线程,或者阻塞它对您来说是可以的,那么您应该使用它,因为尝试使用TPL实际上不会给您带来任何好处。
var task = Task.Factory.FromAsync(BeginIOMethod, EndIOMethod, ... );
await task;这将在不使用线程的情况下异步执行操作,还将等待操作异步完成,这要感谢await。阻塞线程总数: 0。
如果您想要利用异步,并且可以使用C# 5.0,那么应该使用它。
var task = Task.Factory.FromAsync(BeginIOMethod, EndIOMethod, ... );
task.ContinueWith(() => /* rest of the method here */);这将在不使用线程的情况下异步执行操作,还将等待操作异步完成,这要感谢ContinueWith()。阻塞线程总数: 0。
如果您想要利用异步,并且不能使用C# 5.0,那么应该使用它。
发布于 2013-07-02 17:49:30
(1)将(很可能)导致.NET线程池处理Task。
(2)将使用您的BeginIOMethod / EndIOMethod对本机使用的任何机制来处理异步部分,该部分可能涉及或不涉及.NET线程池。
例如,如果您的BeginIOMethod正在通过internet发送一条TCP消息,并且稍后收件人将向您发送一条TCP消息作为响应(由EndIOMethod接收),则.NET线程池不会提供该操作的异步性质。正在使用的TCP库提供异步部件。
这可以通过使用 class来实现。Task.Factory.FromAsync可以创建一个TaskCompletionSource<T>,返回它的Task<T>,然后使用EndIOMethod作为触发器将Result放置到调用时从Task.Factory.FromAsync返回的Task<T>中。
在资源利用方面,性能有什么不同?
(1)和(2)之间的区别主要在于.NET线程池是否会添加其工作负载。通常,如果您只有一个Task.Factory.FromAsync / End...对,而另有一个Task.Factory.StartNew,则正确的做法是选择Task.Factory.StartNew。
如果您使用的是C# 5.0,那么您应该使用非阻塞await task;而不是task.Wait();。(见svick的回答)
https://stackoverflow.com/questions/17432306
复制相似问题