Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/307.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# 在parallel.ForEach循环中获取线程id_C#_Multithreading_Parallel.foreach - Fatal编程技术网

C# 在parallel.ForEach循环中获取线程id

C# 在parallel.ForEach循环中获取线程id,c#,multithreading,parallel.foreach,C#,Multithreading,Parallel.foreach,有没有办法在Parallel.FoEach循环中找到线程id。我尝试使用var threadId=Thread.CurrentThread.ManagedThreadId-1,但它没有提供我要查找的正确索引 下面是一个简单的例子: private void TestProgram() { int numThreads = 1; var values = new List<float>(); for (int i = 0; i

有没有办法在Parallel.FoEach循环中找到线程id。我尝试使用
var threadId=Thread.CurrentThread.ManagedThreadId-1,但它没有提供我要查找的正确索引

下面是一个简单的例子:

private void TestProgram()
    {
        int numThreads = 1;

        var values = new List<float>();
        for (int i = 0; i < numThreads; ++i)
        {
            values.Add(i);
        }

        var data = new List<int>();
        for (int i = 0; i < numThreads; ++i)
        {
            data.Add(i);
        }


        Parallel.ForEach(data, new ParallelOptions{MaxDegreeOfParallelism = numThreads}, i =>
            //foreach (var i in data)
        {
            var threadId = Thread.CurrentThread.ManagedThreadId - 1; // make the index to start from 0

            values[threadId] += i;
        });
    }
private void TestProgram()
{
int numThreads=1;
var值=新列表();
对于(int i=0;i
//foreach(数据中的var i)
{
var threadId=Thread.CurrentThread.ManagedThreadId-1;//使索引从0开始
值[threadId]+=i;
});
}
即使将
MaxDegreeOfParallelism设置为1
,我仍然会将
threadId
设置为大于1

在上述场景中,有没有办法在Parallel.ForEach中找到线程id


注意:我可以使用Parallel。例如在我使用的示例中。但我的问题是在并行中找到它。ForEach

线程ID由底层环境分配,不能保证从0到[num of threads],甚至不能保证在不同的运行中保持一致

关于ThreadID只有少数几个合同,即使这些合同也不能保证:

  • 您将无法获得线程ID 0
  • ThreadID 1通常为主线程保留

    • 您几乎总是会得到一个大于1的线程ID。并行操作将在线程池线程上调度。由于这些线程是在应用程序启动后创建的,因此已经启动了一个线程ID

      var data = new[] { 0,0,0,0,0,0,0,0,0,0,0,0,0};
      
      
          Parallel.ForEach(data, new ParallelOptions{MaxDegreeOfParallelism = 10}, i =>
          {
              Console.WriteLine(System.Threading.Thread.CurrentThread.ManagedThreadId);
          });
      
      我得到输出:

      180 180 180 180 180 180 180 180 62 62 62 62 180


      这是典型的。这是一个环境ID,与您的foreach循环几乎没有关系。您还可以看到,在本例中,.NET不认为需要升级到MaxDegreeOfParallelism(这是您的另一个假设)。

      由于Parallel.ForEach是任务库的一部分,Task.CurrentId将使您更接近您所要查找的内容:

         var data = new[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
      
      
         Parallel.ForEach(data, new ParallelOptions { MaxDegreeOfParallelism = 4 }, i =>
         {
                  Console.WriteLine(Task.CurrentId);
         });
      
      输出为1 1. 1. 1. 1. 1. 1. 1. 1. 1. 2. 2. 一,

      但是,文件中有一项免责声明:

      任务ID是按需分配的,不一定代表 创建任务实例的顺序。注意,尽管 冲突非常罕见,不能保证任务标识符是正确的 独一无二


      由于这在.NET中似乎不可用,只需将看似随机的值映射回从零开始的值即可

      下面是一个示例,您可以根据需要创建资源,每个线程一个。“锁定器”用于防止线程相互干扰。还请注意,列表应替换为线程安全对象,如System.Collections.Concurrent.ConcurrentBag

      object locker = new object();
      List<int> ids = new List<int>();
      List<object> resources = new List<object>();
      
      Parallel.For(0, 20000, x =>
      {
          int thread_id = ids.IndexOf(Environment.CurrentManagedThreadId);
          if (thread_id == -1)
          {                    
              ids.Add(Environment.CurrentManagedThreadId);
              thread_id = ids.IndexOf(Environment.CurrentManagedThreadId);                    
          }
      
          while (resources.Count < thread_id + 1)
          {
              lock (locker)
              {
                  resources.Add(new object());
              }
          }
      
          object resource = resources[thread_id];
          // do stuff with the resource
      });
      
      objectlocker=newobject();
      列表ID=新列表();
      列表资源=新列表();
      对于(0,20000,x=>
      {
      int thread_id=ids.IndexOf(Environment.CurrentManagedThreadId);
      如果(线程id==-1)
      {                    
      Add(Environment.CurrentManagedThreadId);
      thread_id=ids.IndexOf(Environment.CurrentManagedThreadId);
      }
      while(resources.Count
      Parallel可能重复。Foreach是并行任务库的一部分。请改为尝试Task.CurrentId,并查看其行为。