C# 使用线程数组
我是线程新手,所以这对你来说可能很简单,但我已经花了几个小时试图弄明白 假设我有一个函数C# 使用线程数组,c#,multithreading,C#,Multithreading,我是线程新手,所以这对你来说可能很简单,但我已经花了几个小时试图弄明白 假设我有一个函数 public double Gain(List<int> lRelevantObsIndex, ushort uRelevantAttribute) 它需要一些时间才能完成,但它是一个只读函数 我有一个ushort[]值数组,我想得到实现增益函数最小值的ushort值 到目前为止,我已经掌握了以下信息,但它不起作用: LRElevationToBSIndex是只读索引 LRelevatAttr
public double Gain(List<int> lRelevantObsIndex, ushort uRelevantAttribute)
它需要一些时间才能完成,但它是一个只读函数
我有一个ushort[]值数组,我想得到实现增益函数最小值的ushort值
到目前为止,我已经掌握了以下信息,但它不起作用:
LRElevationToBSIndex是只读索引
LRelevatAttributes是ushort值的列表
//Initialize the threads
double[] aGains = new double[lRelevantAttributes.Count];
Thread[] aThreads = new Thread[lRelevantAttributes.Count];
for (int i = 0; i < lRelevantAttributes.Count; i++)
{
aThreads[i] = new Thread(() => aGains[i] = Gain(lRelevantObsIndex, lRelevantAttributes[i]));
aThreads[i].Start();
}
//Join the threads
for (int i = 0; i < lRelevantAttributes.Count; i++)
aThreads[i].Join();
//The easy part - find the minimum once all threads are done
ushort uResult = 0;
double dMinGain = UInt16.MaxValue;
for (int i = 0; i < lRelevantAttributes.Count; i++)
{
if (aGains[i] < dMinGain)
{
dMinGain = aGains[i];
uResult = lRelevantAttributes[i];
}
}
return uResult;
我知道这是一个简单的多线程问题,但仍然需要你的大脑,因为我是新手。这个问题有点棘手:for循环在这里使用了一个修改过的值,即所谓的
这将解决问题,因为lambdas将在循环的每次迭代中捕获临时变量i的当前值。这一个有点棘手:for循环在这里使用一个修改后的值,即所谓的
这将解决问题,因为lambdas将在循环的每次迭代中捕获临时变量i的当前值。我不确定这是否是您的问题,但这是一个问题:
我不确定这是否是你的问题,但这是一个问题: 你也可以这样做 你也可以这样做
当你说它不起作用时,你能更具体一点吗?它以什么方式不起作用?行为是什么?@dvnrrs,当然,它会在第一个for循环中抛出一个异常。它正在尝试访问数组[i],而i设置为30。我猜这是因为线程使用不当造成的。好吧,是的,这是下面答案中描述的访问修改的闭包问题的结果。您实际需要的更像是Parallel.ForEachlRelevantAttributes。。。。我怀疑在这里创建单独的线程是否经济,你测量过什么吗?。这当然是很难做到的。当你说它不起作用时,你能更具体一点吗?它以什么方式不起作用?行为是什么?@dvnrrs,当然,它会在第一个for循环中抛出一个异常。它正在尝试访问数组[i],而i设置为30。我猜这是因为线程使用不当造成的。好吧,是的,这是下面答案中描述的访问修改的闭包问题的结果。您实际需要的更像是Parallel.ForEachlRelevantAttributes。。。。我怀疑在这里创建单独的线程是否经济,你测量过什么吗?。这当然是很难做到的。这正是问题所在;我比我想承认的更喜欢这个。记住,伙计们——lambda不是在循环中计算的,它们在任何变量上都是闭合的,并且在您实际调用它们时进行计算;在这种情况下,在一些背景线程集上。这正是问题所在;我比我想承认的更喜欢这个。记住,伙计们——lambda不是在循环中计算的,它们在任何变量上都是闭合的,并且在您实际调用它们时进行计算;在本例中,在一些背景线程集上。
for (int i = 0; i < lRelevantAttributes.Count; i++)
{
aThreads[i] = new Thread(() => aGains[i] = Gain(lRelevantObsIndex, lRelevantAttributes[i]));
aThreads[i].Start();
}
for (int ii = 0; ii < lRelevantAttributes.Count; ii++)
{
var i = ii; // Now i is a temporary inside the loop, so its value will be captured instead
aThreads[i] = new Thread(() => aGains[i] = Gain(lRelevantObsIndex, lRelevantAttributes[i]));
aThreads[i].Start();
}
for (int i = 0; i < lRelevantAttributes.Count; i++)
{
aThreads[i] = new Thread(() => aGains[i] = Gain(lRelevantObsIndex, lRelevantAttributes[i]));
aThreads[i].Start();
}
for (int i = 0; i < lRelevantAttributes.Count; i++)
{
int j = i;
aThreads[i] = new Thread(() => aGains[j] = Gain(lRelevantObsIndex, lRelevantAttributes[j]));
aThreads[i].Start();
}
[Fact]
public void Test()
{
List<Task<int>> tasks = Enumerable.Range(0, 5) //- it's equivalent how many threads
.Select(x => Task.Run(() => DoWork(x)))
.ToList();
int[] result = Task.WhenAll(tasks).Result; //- Join threads
result.ToList().ForEach(Console.WriteLine);
}
private int DoWork(int taskId)
{
return taskId;
}
3
0
1
2
4