Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/326.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 一个任务中的秒表似乎在所有任务中都是累加的,您只想测量任务间隔吗_C#_Synchronization_Closures_Task Parallel Library_Stopwatch - Fatal编程技术网

C# 一个任务中的秒表似乎在所有任务中都是累加的,您只想测量任务间隔吗

C# 一个任务中的秒表似乎在所有任务中都是累加的,您只想测量任务间隔吗,c#,synchronization,closures,task-parallel-library,stopwatch,C#,Synchronization,Closures,Task Parallel Library,Stopwatch,我在循环中运行,并以以下方式启动任务: var iResult = new List<Task>(); foreach(var i in myCollection) { var task = Task.Factory.StartNew(() => DoSomething(), TaskCreationOptions.LongRunning); task.ContinueWith(m => myResponseHand

我在循环中运行,并以以下方式启动任务:

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

当我反复浏览我的
myMsg
列表时,elaspedmissions似乎是完全相加的-第一个列表上的elaspedmissions可能是300,但最后一个可能是50000(50秒)-这实际上是整个运行所需的大致时间(由另一个计时器测量)。每个任务都有自己的计时器,它们都是在大约相同的时间(或者当线程分配给任务时)的某个地方启动的,但是长时间运行的任务会将它们全部抵消

你永远不会有一个无限的线程池和任务句柄,谁获得了线程,何时获得

关于长跑:

“它本身并不是一个特定的长度。如果您正在生成大量任务,那么长时间运行不适合它们。如果生成一个或两个任务将持续相当长的时间,相对于应用程序的生命周期,那么LongRunning是值得考虑的。一般来说,除非你真的需要它,否则不要使用它。在幕后,它将导致使用更多的线程,因为它的目的是允许线程池继续处理工作项,即使一个任务运行了很长一段时间;如果该任务在池中的线程中运行,则该线程将无法服务于其他任务。如果通过性能测试发现不使用LongRunning会导致处理其他工作的长时间延迟,则通常只使用LongRunning。“-Stephen Toub

编辑:

哎呀,我一开始也很困惑

问题在于,它看起来只是一个aditive(累加),因为ElapsedTime值总是以递增的顺序输出

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

  • 首次启动任务的持续时间为10秒(10000毫秒)
  • 第二个任务的持续时间为8秒(8000毫秒)
  • 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
原因很明显——因为更快的任务总是在更长(更耗时)的任务之前完成并输出

使用系统;
使用System.Collections.Generic;
使用系统线程;
使用System.Threading.Tasks;
使用系统诊断;
命名空间控制台应用程序1
{
班级计划
{
静态void Main(字符串[]参数)
{
var iResult=新列表();
对于(int i=5;i>2;i--)
{
int荷载=i;
var task=task.Factory.StartNew(()=>
DoSomething(加载)、TaskCreationOptions.LongRunning);
//以下注释行不会更改有问题的行为
task.ContinueWith(m=>Console.WriteLine(“from main”+m.Result));
//i结果添加(任务);
}
Console.ReadLine();
}
//公共静态myMsg DoSomething()
公共静态长剂量测量(内载)
{
秒表计时器=System.Diagnostics.Stopwatch.StartNew();
//使用prev或以下两行都会产生相同的结果
//秒表计时器=新秒表();//而不是上一个.StartNew();
//timer.Start();//而不是prev.StartNew();
Console.WriteLine(“***在调用DoLongRunningTask()之前”)
+计时器。延时毫秒);
WriteLine(“GetHashCode”+timer.GetHashCode());
多龙运行任务(load);
timer.Stop();
长时间运行=timer.elapsedmillisons;
控制台写入线(“从DoSomething”+经过);
return appeased;//返回新的myMsg(timer.elaspedmissions);
}
公共静态void DoLongRunningTask(int-load)
{
线程睡眠(2000*负载);
/*******************计算密集型负载的另一种变体
荷载=荷载;
双结果=0;
对于(int i=1;i
如果
DoLongRUnningTask()
锁定共享数据段,很可能计时器的加法是正确的,因为每个计时器都会启动,然后暂停,直到前一个数据段完成。尝试用一个简单的延迟任务替换它,看看它是否计时正确。@Bobson,在任何共享图片上都没有任何锁定data@LightStriker,那么如果“
DoLongRunningTask()
可能不是正确的多线程”,即使它正在重用同一个专用线程(这很可能是由于
TaskCreationOptions.LongRunning
)?即使我显式创建了新实例
Stopwatch timer=new Stopwatch()
或在使用前重置时间,
计时器.elapsedmillesons
值是累积/递增到上一个实例您没有无限的线程数。代码不能也不会以无限并行方式运行。这取决于您的计算机、软件、操作系统、任务参数以及代码的运行方式一个线程被编译后,任务不太可能只共享一个线程,然后一个接一个地得到解决。每个任务可能会等待前一个任务完成。可以尝试的一件事是消除任务开销,直接运行线程。但是如果操作系统只为进程分配一个线程,则
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) );
       */
    }
  }
}