[英]Get a thread id inside parallel.ForEach loop
有没有办法在 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;
});
}
即使在将MaxDegreeOfParallelism to 1
设置MaxDegreeOfParallelism to 1
,我仍然让threadId
大于 1。
有没有办法在上面的场景中找到 Parallel.ForEach 中的线程 ID?
注意:我可以在我使用的示例中使用 Parallel.For。 但我的问题是在 Parallel.ForEach 中找到它
由于 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 1
但是,文档中有免责声明:
任务 ID 是按需分配的,不一定代表创建任务实例的顺序。 请注意,虽然冲突非常罕见,但不能保证任务标识符是唯一的。
ThreadID 由底层环境分配,并不能保证从 0 到 [线程数] 甚至从运行到运行是一致的。
关于 threadID 的合同只有几个,甚至这些也不能保证:
您几乎总是会得到一个大于 1 的线程 ID。 并行操作将在线程池线程上调度。 由于这些线程是在应用程序启动后创建的,因此线程 ID 为 1 就已经启动了。
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。
由于这在 .NET 中似乎不可用,因此只需将看似随机的值映射回从零开始的值。
示例如下,您可以根据需要创建资源,每个线程一个。 'locker'是为了防止线程相互干扰。 另请注意,列表应替换为线程安全对象,如 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
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.