注意我很清楚我在问什么,并且我无法在正常情况下使用这样的功能,但它被用作研究我正在进行的因子实验研究生项目的因素。
我有以下功能,我想使用PLINQ(非TPL)运行。我知道PLINQ在TPL之上运行,但这部分实验。另外,除非我不知道用PLINQ做另一种方式,我相信我必须在某种程度上“破解”使用带递归的for循环的阶乘方法。
由于Parallel类只提供For,ForEach和Invoke,它不提供我需要的东西,例如TPL做什么,我需要它返回,而Invoke不会这样做,所以我将不得不使用For和do每次递归调用从0开始的for循环(是的,我知道它看起来很荒谬)。
我想做以下事情:
public ulong RecursivePLINQ(ulong factor)
{
if (factor > 1)
{
Parallel.For<ulong>(0, 1, () => factor, (j, loop, factorial) =>
{
Thread.Sleep(1); /*Simulate Moderate Operation*/
return factorial * RecursivePLINQ(--factorial);
}, (i) => { });
}
return 1;
}
目前,正在发生的事情似乎正在起作用,但在最后的调用中它返回1,并且递归调用的结果是1,而不是递归更改的值。我似乎无法遇到什么问题。我在这里显示了备用TPL实现(再次用于研究),这是有效的。
public ulong RecursiveTPL(ulong factor)
{
if (factor > 1)
{
Task<ulong> task = new Task<ulong>((f) =>
{
Thread.Sleep(1); /*Simulate Moderate Operation*/
ulong val = (ulong)f;
return factor * RecursiveTPL(--val);
}, factor);
task.Start();
task.Wait();
return task.Result;
}
return 1;
}
*** 请不要因为我的要求而激怒我,这是一个非常具体的研究目的的 * ****
编辑我在MSDN文档上看到了一个示例,它显示了线程局部变量的使用,所以我尝试了类似的东西,但我的头开始旋转一点......不要注意铸造,它只是为了看我是否可以让它工作......
public ulong RecursivePLINQ(ulong factor)
{
long total = 0;
if (factor > 1)
{
Parallel.For<ulong>(0, 1, () => factor, (j, loop, factorial) =>
{
Thread.Sleep(1); /*Simulate Moderate Operation*/
return factorial * RecursivePLINQ(--factorial);
}, (i) => Interlocked.Add(ref total,(long)i)
);
}
return (ulong)total;
}
答案 0 :(得分:2)
它不漂亮,我真的不确定这对我的目的是否有效,但它确实给了我正确的因子。我得到了这个解决方案,但是我必须对总参数进行校正以使其工作,不确定我会称之为什么,或者是否有更好的方法来实现它,但现在必须这样做。 ..
public long RecursivePLINQ(long factor,long total)
{
if(total == 0)
{
total = 1;
}
if (factor > 1)
{
Parallel.For<long>(0, 1, () => factor, (j, loop, factorial) =>
{
Thread.Sleep(1); /*Simulate Moderate Operation*/
total = factorial * RecursivePLINQ(--factorial, total);
return total;
}, (i) => {return;});
}
return total;
}
答案 1 :(得分:1)
从this Dr Dobbs article无耻地复制,您可以使用聚合扩展方法来计算阶乘:
int value=5;
var factorial=Enumerable.Range(1, value).AsParallel()
.Aggregate(1, (result, number)=>
result*number, result=>result);
您可以争辩说Aggregate会执行您手动执行的递归,或者您可以编写递归调用自身来计算阶乘的代码。
然而,和其他人一样,我看不到你会完成什么。你的代码将由PLINQ的设置和拆卸主导,你得到的任何数字都将毫无意义。如果有的话,PLINQ用于使用一系列可以并行执行的运算符来替换循环代码,而程序员不必指定这将如何发生。