2010-10-18 2 views
4

J'expérimente le support des tâches dans .NET 4.0 - spécifiquement avec le support de continuation. Ce que je suis perplexe, c'est que je ne peux pas comprendre comment obtenir une continuation avec le drapeau TaskContinuationOptions.OnlyOnCanceled à exécuter. Si je fais un ThrowIfCancellationRequested dans ma routine de travail, il semble seulement se propager hors de la continuation comme une faute au lieu d'une opération d'annulation. Par exemple, étant donné ce code:Bibliothèque parallèle de tâches - Comment obtenir une continuation avec TaskContinuationOptions.OnlyOnCanceled to Fire?

using System; 
using System.Threading; 
using System.Threading.Tasks; 

namespace TaskExp1 
{ 
    class Program 
    { 
     static void Main() 
     { 
      var n = 10000; 

      DumpThreadId("main method"); 

      var cts = new CancellationTokenSource(); 
      var task = Task.Factory.StartNew<int>(_ => Sum(cts.Token, n), 
                cts.Token); 

      task.ContinueWith(t => 
      { 
       DumpThreadId("ContinueWith Completed, ", newline:false); 
       Console.WriteLine("The result is " + t.Result); 
      }, TaskContinuationOptions.OnlyOnRanToCompletion); 

      task.ContinueWith(t => 
      { 
       DumpThreadId("ContinueWith Faulted, ", newline: false); 
       Console.WriteLine(t.Exception.InnerExceptions[0].Message); 
      }, TaskContinuationOptions.OnlyOnFaulted); 

      task.ContinueWith(_ => 
      { 
       DumpThreadId("ContinueWith Cancelled, "); 
      }, TaskContinuationOptions.OnlyOnCanceled); 

      Console.WriteLine("Computing sum of " + n + " ..."); 
      Thread.SpinWait(100000); 
      cts.Cancel(); 

      Console.WriteLine("Done."); 
      Console.ReadLine(); 
     } 

     static int Sum(CancellationToken cancelToken, int n) 
     { 
      DumpThreadId("from Sum method"); 
      int sum = 0; 
      for (; n > 0; n--) 
      { 
       Thread.SpinWait(500000); 
       if (n == 10000) cancelToken.ThrowIfCancellationRequested(); 
       checked { sum += n; } 
      } 
      return sum; 
     } 

     static void DumpThreadId(string msg = "", bool newline = true) 
     { 
      var formattedMsg = String.Format("ThreadId: {0} {1}", 
            Thread.CurrentThread.ManagedThreadId, msg); 
      if (newline) formattedMsg += "\n"; 
      Console.Write(formattedMsg); 
     } 
    } 
} 

Ce sorties:

ThreadId: 9 main method 
Computing sum of 10000 ... 
Done. 
ThreadId: 10 from Sum method 
ThreadId: 10 ContinueWith Faulted, The operation was canceled. 

Comment quitter ma méthode travailleur (Somme) de telle sorte que la poursuite OnlyOnCanceled est congédié?

Répondre

5

Lorsque vous utilisez le _ => expression lambda que vous utilisez la surcharge

Func<Object, TResult> function, Object state 

. Si vous changez le Factory.StartNew à

Task.Factory.StartNew<int>(() => Sum(cts.Token, n), cts.Token); 

il appellera le "ContinueWith Annulé".

+0

Wow qui semble subtile mais logique - en utilisant _! = Pour utiliser(). Merci! –

Questions connexes