5

Sono in esecuzione in un ciclo e dando il via le attività nel modo seguente:Cronometro in una Task sembra essere additivo in tutti i compiti, vogliono misurare l'intervallo solo compito

var iResult = new List<Task>(); 
foreach(var i in myCollection) 
{ 
    var task = Task.Factory.StartNew(() => 
        DoSomething(), TaskCreationOptions.LongRunning); 
    task.ContinueWith(m => myResponseHandler(m.Result)); 
    iResult.Add(task); 
} 

Entro il mio metodo DoSomething(), ho avere un timer:

public static myMsg DoSomething() 
{ 
    var timer = System.Diagnostics.Stopwatch.StartNew(); 
    DoLongRunningTask(); //If it matters this hits a REST endpoint (https) 
    timer.Stop(); 

    return new myMsg(timer.ElaspedMilliseconds); 
} 

Quando ho scorrere la mia lista di myMsg s' i ElaspedMilliseconds sembra essere completamente additiva - le ElaspedMilliseconds sul primo potrebbe essere 300, ma l'ultima potrebbe essere 50000 (50 secondi) - che è in realtà l'a tempo approssimativo per l'esecuzione dell'intera operazione (misurata da un altro timer).

+1

Aggiornato [risposta] (http://stackoverflow.com/a/16259019/200449). Sembra solo additivo perché i valori di ElapsedMilliseconds vengono sempre emessi in ordine crescente SOLO - in ordine di completamento delle attività (in ordine di durata dell'attività) che non è l'ordine in cui sono state avviate le attività –

risposta

2

Edit:

Ops, mi è stato anche il primo confuso.

Il problema è che sembra solo aditivo (cumulativo) perché i valori di ElapsedTime vengono sempre emessi solo in ordine crescente.

Quindi, se ho, come nel mio demo qui di seguito, in ordine di lancio:

  • durata prima del compito lanciato di 10 sec (10000 msec),
  • la durata della seconda del compito di 8 sec (8 000 ms),
  • durata dell'attività 3D di 6 sec (6 000 ms),

quindi visualizzare i risultati nella uscita su ordine iniziale - SEMPRE in ordine di sempre più dinamico Durata ng di compiti:

  • il primo in uscita: durata 3d lanciato del compito (della durata di 6 sec)
  • il secondo in uscita: la durata dell'attività 2 ° lanciato (di 8 sec durata)
  • la 3d (ultima) in uscita: la durata della prima lanciato del compito (di 10 sec durata)

Ecco l'output di console app di seguito:

from DoSomething 6043 
from main 6043 
from DoSomething 8057 
from main 8057 
from DoSomething 10058 
from main 10058 

Ed è ovvio perché - perché l'attività più veloce termina sempre e restituisce un compito più lungo (più dispendio di tempo).

using System; 
using System.Collections.Generic; 
using System.Threading; 
using System.Threading.Tasks; 
using System.Diagnostics; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
    static void Main(string[] args) 
    { 
     var iResult = new List<Task>(); 
     for (int i=5; i>2; i--) 
     { 
     int load = i; 
     var task = Task.Factory.StartNew(() => 
         DoSomething(load), TaskCreationOptions.LongRunning); 
     //following commented lines do NOT change the behavior in question 
     task.ContinueWith(m => Console.WriteLine("from main "+m.Result)); 
     //iResult.Add(task); 
     } 
     Console.ReadLine(); 
    } 

    //public static myMsg DoSomething() 
    public static long DoSomething(int load) 
    { 
     Stopwatch timer = System.Diagnostics.Stopwatch.StartNew(); 

     //usage of either prev or following 2 lines produce the same results 
     //Stopwatch timer = new Stopwatch(); //instead of prev .StartNew(); 
     //timer.Start();// instead of prev .StartNew(); 

     Console.WriteLine("***Before calling DoLongRunningTask() " 
       + timer.ElapsedMilliseconds); 
     Console.WriteLine("GetHashCode "+timer.GetHashCode()); 

     DoLongRunningTask(load); 
     timer.Stop(); 

     long elapsed = timer.ElapsedMilliseconds; 
     Console.WriteLine("from DoSomething "+ elapsed); 

     return elapsed;//return new myMsg(timer.ElaspedMilliseconds); 
    } 

    public static void DoLongRunningTask(int load) 
    { 
     Thread.Sleep(2000*load); 
     /******************* another variant of calculation intensive loading 
      load = load; 
      double result = 0; 
      for (int i = 1; i < load*100000; i++) 
        result += Math.Exp(Math.Log(i)); 
     */ 
    } 
    } 
} 
+1

Perché il carico cambia tra le attività? Dovrebbero durare lo stesso tempo. – LightStriker

2

Una cosa che è più probabile che accada è che DoLongRunningTask() potrebbe non essere multithreading correttamente, il che significa che un'attività viene eseguita dopo che il primo è stato completato e così via. Ogni attività ha il proprio timer e iniziano tutte da qualche parte intorno allo stesso tempo (o come i thread sono allocati alle attività), ma l'attività a lunga esecuzione li compensa tutti.

Non si dispone mai di un pool di thread illimitato e di handle di attività che ricevono una discussione e quando.

Circa LongRunning:..

"Non è una lunghezza specifica per sé Se si sta generando un sacco di compiti, LongRunning non è adatto per loro se si sta generando uno o due attività che persisterà per un po 'di tempo relativamente alla durata della tua applicazione, quindi LongRunning è qualcosa da considerare.In generale, non usarlo a meno che non trovi che ne hai davvero bisogno. Sotto le copertine, si otterrà un numero maggiore di thread in uso, perché il suo scopo è quello di consentire a ThreadPool di continuare a elaborare gli elementi di lavoro anche se un'attività è in esecuzione per un lungo periodo di tempo, se tale attività era in esecuzione in un thread dal pool, quella thread non sarebbe in grado di servizio altre attività. Solitamente si utilizza solo LongRun se si è scoperto che attraverso il test delle prestazioni il mancato utilizzo ha causato lunghi ritardi nell'elaborazione di altri lavori ". - Stephen Toub

+0

Solo per elaborare su questo, se 'DoLongRUnningTask() 'si blocca su una porzione di dati condivisa, è del tutto possibile che il timer * sia * corretto nell'essere additivo, poiché ognuno inizia, quindi si interrompe finché non viene eseguito quello precedente. Prova a sostituirlo con un semplice compito di ritardo e verifica se il tempo è scaduto. – Bobson

+0

@Bobson, [Sto riproducendo lo stesso] (http://stackoverflow.com/a/16259019/200449) senza alcun blocco su un dato anishared di dati –

+0

@LightStriker, quindi cosa fare se "' DoLongRunningTask() 'potrebbe non essere multithreaded correttamente ", anche se sta riutilizzando lo stesso thread dedicato (cosa molto probabilmente dovuta a' TaskCreationOptions.LongRunning')? Anche quando creo in modo esplicito nuove istanze 'Cronometro timer = nuovo Cronometro();' o ripristina il tempo prima di usarlo, il valore 'timer.ElapsedMilliseconds' è cumulativo/incrementale rispetto alle istanze precedenti –