任务中的秒表似乎是所有任务的附加,想要测量任务间隔

Pre*_*ott 6 c# synchronization closures stopwatch task-parallel-library

我正在循环运行并以下列方式开始执行任务:

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);
}
Run Code Online (Sandbox Code Playgroud)

在我的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);
}
Run Code Online (Sandbox Code Playgroud)

当我遍历我的列表时,myMsgElaspedMilliseconds似乎完全是加法的 - 第一个上的ElaspedMilliseconds可能是300,但最后一个可能是50000(50秒) - 这实际上是整个事情所需的大致时间运行(由另一个计时器测量).

Gen*_*нин 3

编辑:

哎呀,我一开始也很困惑。

问题是它看起来只是累加(累积),因为 ElapsedTime 值始终仅按递增顺序输出。

因此,如果我有,如下面的演示所示,按启动顺序:

  • 第一个启动任务的持续时间为 10 秒(10000 毫秒),
  • 第二个任务的持续时间为 8 秒(8 000 毫秒),
  • 3d 任务的持续时间为 6 秒(6000 毫秒),

那么结果会按照初始顺序出现在输出中 - 始终按照任务持续时间递增的顺序:

  • 输出中的第一个:3d 启动任务的持续时间(6 秒持续时间)
  • 输出中的第二个:第二个启动任务的持续时间(8 秒持续时间)
  • 输出中的第 3d 个(最后一个):第一个启动任务的持续时间(持续时间为 10 秒)

以下是控制台应用程序的输出:

from DoSomething  6043  
from main  6043  
from DoSomething  8057  
from main  8057  
from DoSomething  10058
from main  10058
Run Code Online (Sandbox Code Playgroud)

原因很明显 - 因为更快的任务总是在更长(更耗时)的任务之前完成并输出。

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) );
       */
    }
  }
}
Run Code Online (Sandbox Code Playgroud)