2012-01-20 10 views
6

Na stronie 33 książki Stephena Toub zaZadanie vs AsParallel()

http://www.microsoft.com/download/en/details.aspx?id=19222

Jest kod

var pings = from addr in addrs.AsParallel().WithDegreeOfParallelism(16) 
    select new Ping().Send(addr); 
foreach (var ping in pings) 
    Console.WriteLine("{0}: {1}", ping.Status, ping.Address); 

i według Stefana lepsza wersja

var pings = (from addr in addrs 
    select new Ping().SendTask(addr, null)).ToArray(); 
Task.WaitAll(pings); 
foreach (Task<PingReply> ping in pings) 
    Console.WriteLine("{0}: {1}", ping.Result.Status, ping.Result.Address); 

Stephen mówi, że druga opcja jest lepsza, ponieważ "abstrakcja zadań może być również używana do reprezentowania Operacje związane z I/O i bez wiązania wątku w procesie . "

Ale czy zadanie po prostu nie korzysta z Threadpool (a więc po prostu za pomocą wątków) pod spodem? Więc w rzeczywistości przywiązujesz wątek?

+2

"Zadanie nie korzysta po prostu z Threadpool" - to nie byłaby abstrakcja. –

Odpowiedz

4

Nie wszystkie zadania oznaczają pracę do wykonania w wątku. Prawie każde zadanie zwrócone od TaskCompletionSource reprezentuje coś "innego". A jeśli zagłębić się metodą SendTask znajdujemy wywołuje SentTaskCore:

private static Task<PingReply> SendTaskCore(Ping ping, object userToken, Action<TaskCompletionSource<PingReply>> sendAsync) 
    { 
     // Validate we're being used with a real smtpClient. The rest of the arg validation 
     // will happen in the call to sendAsync. 
     if (ping == null) throw new ArgumentNullException("ping"); 

     // Create a TaskCompletionSource to represent the operation 
     var tcs = new TaskCompletionSource<PingReply>(userToken); 

     // Register a handler that will transfer completion results to the TCS Task 
     PingCompletedEventHandler handler = null; 
     handler = (sender, e) => EAPCommon.HandleCompletion(tcs, e,() => e.Reply,() => ping.PingCompleted -= handler); 
     ping.PingCompleted += handler; 

     // Try to start the async operation. If starting it fails (due to parameter validation) 
     // unregister the handler before allowing the exception to propagate. 
     try 
     { 
      sendAsync(tcs); 
     } 
     catch(Exception exc) 
     { 
      ping.PingCompleted -= handler; 
      tcs.TrySetException(exc); 
     } 

     // Return the task to represent the asynchronous operation 
     return tcs.Task; 
    } 

Tak, nie, to nie jest blokowanie wątku - jest za pomocą mechanizmów uzupełniania asynchroniczny, aby uniknąć uruchamiania wątku.


Od docs na TaskCompletionSource:

Reprezentuje strony producenta zadania niezwiązanego z delegatem, zapewniając dostęp do strony konsumenta za pośrednictwem właściwości zadań.

Tak, jak mówi, że obsługuje Task, który nie jest związany z delegatem - pozwala przekazać komuś Task, a następnie zgrać jak to zadanie zostanie zakończone, gdy realizacja wiąże się coś inne niż wykonywanie delegata.

+1

Po to, aby wyjaśnić, chociaż nie rozumiem jeszcze w pełni kodu, ale można zrobić "asynchroniczne mechanizmy realizacji" bez użycia wątku? Jak to jest możliwe? kiedy zrobiłem BeginInvoke na akci, oni powiedzą mi, że faktycznie jest on wysyłany na wątku. – TheWommies