5

를 측정 할 것 : 내 DoSomething() 방법 내에서스톱워치, 모든 작업에서 첨가제가 될 나는 루프에서 실행하고 다음과 같은 방식으로 작업을 발로있어 바로 작업 간격을

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

, I 타이머 가지고있다 - 첫 번째에 ElaspedMilliseconds 300이 될 수도 있지만 마지막은 50000 (50초)이 될 수 나는 myMsg 's를 ElaspedMilliseconds 내 목록을 반복하면

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

완전히 첨가제 것 같다 - 실제로는 pproximate (전체 타이머가 다른 타이머에 의해 측정 됨) 실행에 걸리는 시간.

+1

[내 답변] (http://stackoverflow.com/a/16259019/200449)이 업데이트되었습니다. ElapsedMilliseconds 값은 늘리는 순서대로 항상 출력되기 때문에 단지 거짓으로 보입니다. - 작업이 완료된 순서대로 (작업의 순서대로) 작업이 시작된 순서가 아닙니다. –

답변

2

편집 :

어머, 나 또한 처음으로 혼란스러워했다.

ElapsedTime 값은 항상 증가하는 순서로만 출력되므로 문제는 정량적으로 보입니다 (누적적임).

그래서, 난이있는 경우, 발사의 순서로 아래에있는 내 데모, 같이 :

  • 10 초 (10000 밀리 초)의 첫번째 시작 작업의 기간,
  • 8 초의 두 번째 작업의 기간 (8 000 밀리 초),
  • 다음 결과 초기 순서가 출력에 표시

6 초 (6000 밀리 초)의 3 차원 작업의 기간, - 항상 increasi의 순서로 작업의 NG 기간 :

  • 출력 1 : 2 시작 작업의 지속 시간 (8 초 기간)
  • :
  • 출력 2 (6 초 지속 시간) 3 차원 시작 작업의 기간

    from DoSomething 6043 
    from main 6043 
    from DoSomething 8057 
    from main 8057 
    from DoSomething 10058 
    from main 10058 
    
    ,536,913,632 : 여기

아래 콘솔 응용 프로그램의 출력입니다 (10 초 지속 기간) 제 1 회 시작 작업의 기간 : 3 차원 (마지막) 출력 10

그리고 왜 더 빠른 작업은 더 오래 (더 많은 시간이 소요되는) 작업 전에 항상 끝나고 출력되기 때문에 그 이유는 분명합니다.

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

2

가장 많이 발생하는 한 가지는 DoLongRunningTask()이 멀티 스레드가 적절하지 않을 수 있다는 것입니다. 즉, 첫 번째 작업이 완료된 후에 하나의 작업이 실행된다는 의미입니다. 각 작업에는 자체 타이머가 있으며 모두 같은 시간 (또는 스레드가 작업에 할당 된)에서 어딘가에 시작되지만 장기 실행 작업은 모두이를 상쇄합니다.

스레드 풀을 가질 수있는 스레드 풀과 태스크 핸들을 가질 필요가 없습니다.

LongRunning 소개

:.. 당신이 하나 또는 두 개의 작업을 생성하는 경우

"그것은 특정 길이 자체는 작업을 많이 생성하는 경우, LongRunning 그들에 적합하지 않은 지속됩니다 아니에요 응용 프로그램의 수명과 관련하여 꽤 오랜 시간 동안 LongRunning을 고려해야합니다. 일반적으로 필요한 경우가 아니라면 LongRunning을 사용하십시오. 일반적으로이 기능을 사용하면 더 많은 스레드가 생성됩니다 하나의 작업이 장시간 실행 중이 더라도 ThreadPool이 작업 항목을 계속 처리 할 수 ​​있도록하는 것이 목적이기 때문에 그 작업이 풀에서 스레드에서 실행 중이면 그 스레드는 다음 작업을 수행 할 수 없습니다. 일반적으로 LongRun 만 사용합니다. 성능 테스트를 통해 찾지 못했다면 다른 작업을 처리하는 데 오랜 시간 지연이있었습니다. " - 스티븐 Toub

+0

DoLongRUnningTask()'가 공유 된 데이터를 잠 그게되면, 타이머가 * 시작하기 때문에 * 첨가제에 * 맞을 가능성이 높습니다. 이전의 것이 완료 될 때까지 일시 정지합니다. 간단한 지연 작업으로 교체하고 시간이 맞는지 확인하십시오. – Bobson

+0

@Bobson, 데이터의 임의의 공유 된 부분에 잠금을 두지 않고 [똑같은 것을 재현하고 있습니다] (http://stackoverflow.com/a/16259019/200449) @LightStriker –

+0

"DoLongRunningTask()"가 멀티 쓰레드 (multi-threaded) 제대로 ", 같은 전용 스레드를 재사용하고있다하더라도 (아마도 'TaskCreationOptions.LongRunning' 때문에 무엇입니까?)? 새로운 인스턴스'Stopwatch timer = new Stopwatch();를 명시 적으로 만들거나 사용하기 전에 시간을 재설정하더라도'timer.ElapsedMilliseconds' 값은 이전 인스턴스에 누적/증가합니다. –