2016-03-21 65 views
8

除了要求TaskFactory.StartNew仅与“动作”参数的最常见的形式 (1)https://msdn.microsoft.com/en-us/library/dd321439(v=vs.110).aspx为什么要将取消令牌传递给TaskFactory.StartNew?

我们ALSE有一个接受一个额外的参数为“对消令牌” (2)https://msdn.microsoft.com/en-us/library/dd988458.aspx

一个方法

我的问题是,为什么我们应该使用call(2)而不是call(1)?

我的意思是,对于页面中的MSDN的例子(2)将也,如果我没有通过取消标记为参数(因为变量令牌是由委托函数访问的工作是这样:

var tokenSource = new CancellationTokenSource(); 
     var token = tokenSource.Token; 
     var files = new List<Tuple<string, string, long, DateTime>>(); 

     var t = Task.Factory.StartNew(() => { string dir = "C:\\Windows\\System32\\"; 
           object obj = new Object(); 
           if (Directory.Exists(dir)) { 
            Parallel.ForEach(Directory.GetFiles(dir), 
            f => { 
              if (token.IsCancellationRequested) 
               token.ThrowIfCancellationRequested(); 
              var fi = new FileInfo(f); 
              lock(obj) { 
               files.Add(Tuple.Create(fi.Name, fi.DirectoryName, fi.Length, fi.LastWriteTimeUtc));   
              } 
             }); 
           } 
           } 
         ); //note that I removed the ", token" from here 
     tokenSource.Cancel(); 

所以有什么情况发生底下当我通过取消标记以Task.Factory.StartNew?

感谢

回答

7

两件事情会发生。

  1. 如果在调用StartNew之前令牌已被取消,它将永远不会启动线程并且任务将处于Canceled状态。
  2. 如果OperationCanceledException是从任务内部引发的,并且该异常以与StartNew相同的标记传递,则它将导致返回的任务进入Cancelled状态。如果与异常关联的令牌是不同的令牌,或者您未在任务中传递令牌,则会输入Faulted状态。

P.S.如果不通过TaskScheduler,您永远不应该拨打Task.Factory.StartNew,因为如果您不这样做,它可以很容易地cause you to run code on the UI thread that you expected to run on a background thread。除非您绝对需要使用StartNewTask.RunStartNew具有相同的CancellationToken行为,否则请使用Task.Run(

+0

感谢您传播有关不使用'Task.Factory' – kai

相关问题