5

我在一個循環中運行,並以下列方式拉開任務:秒錶在任務似乎是所有任務的添加劑,要測量的只是任務間隔

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); 
} 

在我的DoSomething()方法,我有一個計時器:

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); 
} 

當我通過我的myMsg的的ElaspedMilliseconds的列表迭代似乎是完全添加劑 - 在第一個的ElaspedMilliseconds可能是300,但最後一個可能是50000(50秒), - 這實際上是一個整個事情需要運行的時間(由另一個計時器測量)。

+1

Updated [my answer](http://stackoverflow.com/a/16259019/200449)。它只是看起來似乎是累加性的,因爲ElapsedMilliseconds值總是以遞增順序輸出 - 按任務完成順序(按任務持續時間順序),這不是任務啓動的順序 – 2013-04-28 07:55:02

回答

2

編輯:

哎呀,我也第一次感到困惑。

問題是它只看起來很敏感(累計),因爲ElapsedTime值總是以遞增的順序輸出。

所以,如果我有,下面我的演示,在啓動順序:

  • 10秒(10000毫秒)1日發佈任務的持續時間,
  • 8秒的第二個任務的工期(8 000毫秒),
  • 6秒(6 000毫秒)的3D任務的持續時間,

然後將結果顯示在輸出出初始順序的 - 總是increasi的順序任務的NG時間:

  • 第一輸出:在推出了3D任務的持續時間(6秒的持續時間)
  • 在輸出第2:第二個推出任務的持續時間(8秒的持續時間)
  • 的3D(最後)輸出:第一發射任務的持續時間(10秒的持續時間)

這是從下面的控制檯應用程序的輸出:

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

這很明顯,爲什麼 - 因爲更快的任務總是在更長時間(更耗時)的任務之前完成並輸出。

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

爲什麼負載會在任務間改變?他們應該持續相同的時間。 – LightStriker 2013-04-28 13:40:54

2

最有可能發生的一件事是DoLongRunningTask()可能不是正確的多線程,這意味着一個任務在第一個完成之後運行等等。每個任務都有自己的計時器,它們都在同一時間開始某處(或者線程分配給任務),但是長時間運行的任務將它們全部抵消掉了。

您從來沒有無限的線程池和任務處理誰獲得線程和時間。

關於LongRunning:。

「這不是一個特定的長度本身如果你產生了很多任務,LongRunning是不適合他們。如果你生成一個或兩個任務將持續相對於你的應用程序的生命週期來說,相當長的一段時間,那麼LongRunning是需要考慮的事情。一般來說,除非你發現你真的需要它,否則不要使用它。在封面之下,它會導致更多的線程因爲它的目的是允許ThreadPool繼續處理工作項目,即使一個任務正在運行很長一段時間;如果該任務在池中的線​​程中運行,該線程將無法服務其他任務,通常只使用LongRun如果你通過性能測試發現不使用它會導致其他工作處理的長時間延遲。「 - 斯蒂芬Toub

+0

只是爲了詳細說明,如果'DoLongRUnningTask ()'鎖定共享數據段時,定時器*很可能是加法正確的,因爲每個定時器都啓動,然後暫停直到前一個完成。嘗試用一個簡單的延遲任務替換它,看看是否得到正確的時間。 – Bobson 2013-04-26 16:40:21

+0

@Bobson,[我正在複製相同的](http://stackoverflow.com/a/16259019/200449)沒有任何鎖在數據 – 2013-04-28 03:19:09

+0

@LightStriker數據,所以如果DoLongRunningTask()可能不是多線程正確「,即使它重用了相同的專用線程(最有可能是因爲TaskCreationOptions.LongRunning)。即使當我明確創建新實例'Stopwatch timer = new Stopwatch();'或在使用它之前重置時間,'timer.ElapsedMilliseconds'值將累積/遞增到先前的實例 – 2013-04-28 03:20:23