2011-04-15 80 views
6

这可能是一个非常基本的问题,但只是我想确保自己在脑海中有一席之地。 今天我正在用TPL库进行挖掘,发现有两种创建Task类实例的方法。任务类的实例(Task.Factory.StartNew或TaskCompletionSource)

办法,我

Task<int> t1 = Task.Factory.StartNew(() => 
       { 
        //Some code 
        return 100; 

       }); 

路II

TaskCompletionSource<int> task = new TaskCompletionSource<int>(); 
    Task t2 = task.Task; 
    task.SetResult(100); 

现在,我只是想知道,

  1. 是否有这些实例之间有什么区别?
  2. 如果是,那么是什么?

回答

4

第二个示例不会创建一个“真实”任务,即没有任何委托可以执行任何操作。

您主要使用它来向调用者显示一个任务接口。看一下例子上 msdn

TaskCompletionSource<int> tcs1 = new TaskCompletionSource<int>(); 
    Task<int> t1 = tcs1.Task; 

    // Start a background task that will complete tcs1.Task 
    Task.Factory.StartNew(() => 
    { 
     Thread.Sleep(1000); 
     tcs1.SetResult(15); 
    }); 

    // The attempt to get the result of t1 blocks the current thread until the completion source gets signaled. 
    // It should be a wait of ~1000 ms. 
    Stopwatch sw = Stopwatch.StartNew(); 
    int result = t1.Result; 
    sw.Stop(); 

    Console.WriteLine("(ElapsedTime={0}): t1.Result={1} (expected 15) ", sw.ElapsedMilliseconds, result); 
+2

要添加更多的细节,TaskCompletionSource是一种包装异步操作的方式,否则当前不支持TaskFactory.FromAsync之类的操作。 TaskCompletionSource的一个示例用法是包装基于事件的异步模式实现,如WebClient.DownloadStringAsync。有关更多示例,请参阅http://msdn.microsoft.com/en-us/magazine/ff959203.aspx – 2012-07-22 16:07:02

0

当你不烧任何异步操作远高于1,你是从线程池消耗另一个线程(可能是浪费时间,如果你不改变默认TaskScheduler)。

但是,在方式2中,您正在生成一个完成的任务,并且在与您相同的线程中执行该任务。 TCS也可以看作无线任务(可能是错误的描述,但被几个开发人员使用)。

+0

Task.StartNew是一个异步操作... – 2012-07-22 16:07:43

+0

@PeterRitchie是否读过我写过的内容?如果你要运行一个不需要线程切换但需要返回一个Task对象的代码,你只会使用Task.Factory.StartNew来浪费时间。停止使用它并使用TCS。 – tugberk 2012-07-22 18:12:30

+0

@PeterRitchie和'Task.Factory.StartNew'不是一个神奇的子弹,它不是异步!你可以称它为多线程而不是异步。异步和多线程是不同的。 – tugberk 2012-07-22 18:15:05