C# 在parallel.ForEach循环中获取线程id
有没有办法在Parallel.FoEach循环中找到线程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
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,并查看其行为。