Task.Factory.StartNew与Task.Factory.FromAsync

sol*_*ljy 42 .net c# asynchronous task-parallel-library

假设我们有一个I/O绑定方法(例如进行DB调用的方法).此方法可以同步和异步运行.那是,

  1. 同步:

    IOMethod()
    
    Run Code Online (Sandbox Code Playgroud)
  2. 异步:

    BeginIOMethod()
    EndIOMethod()
    
    Run Code Online (Sandbox Code Playgroud)

然后,当我们以不同的方式执行方法时,如下所示,在资源利用方面的性能差异是什么?

  1. var task = Task.Factory.StartNew(() => { IOMethod(); });
    task.Wait();
    
    Run Code Online (Sandbox Code Playgroud)
  2. var task = Task.Factory.FromAsync(BeginIOMethod, EndIOMethod, ... );
    task.Wait();
    
    Run Code Online (Sandbox Code Playgroud)

svi*_*ick 66

var task = Task.Factory.StartNew(() => { IOMethod(); });
task.Wait();
Run Code Online (Sandbox Code Playgroud)

这将在IOMethod()执行时阻塞线程池线程,并因为这个而阻塞当前线程Wait().总阻塞线程:2.

var task = Task.Factory.FromAsync(BeginIOMethod, EndIOMethod, ... );
task.Wait();
Run Code Online (Sandbox Code Playgroud)

这将(很可能)在不使用线程的情况下异步执行操作,但它会阻止当前线程,因为Wait().总阻塞线程:1.

IOMethod();
Run Code Online (Sandbox Code Playgroud)

这将在IOMethod()执行时阻止当前线程.总阻塞线程:1.

如果您需要阻止当前线程,或者阻止它对你没用,那么你应该使用它,因为尝试使用TPL实际上不会给你任何东西.

var task = Task.Factory.FromAsync(BeginIOMethod, EndIOMethod, ... );
await task;
Run Code Online (Sandbox Code Playgroud)

这将在不使用线程的情况下异步执行操作,并且它还将等待操作异步完成,这要归功于await.被阻止的线程总数:0.

如果您想利用异步并且可以使用C#5.0,那么这就是您应该使用的.

var task = Task.Factory.FromAsync(BeginIOMethod, EndIOMethod, ... );
task.ContinueWith(() => /* rest of the method here */);
Run Code Online (Sandbox Code Playgroud)

这将在不使用线程的情况下异步执行操作,并且它还将等待操作异步完成,这要归功于ContinueWith().被阻止的线程总数:0.

如果您想利用异步并且不能使用C#5.0,那么这就是您应该使用的.

  • 我认为"task.Wait()"仅仅是为了举例而引入的.我确信当任务执行时,OP打算在此过程中做一些额外的事情.所以我认为你不应该将调用线程视为一个被阻塞的线程.但如果他认真等待,那你就是对的. (3认同)
  • @Tombala我在问题中没有看到任何表明这一点的内容。但这肯定是有可能的。 (2认同)