C# 运行大量任务

C# 运行大量任务,c#,task,stack-overflow,C#,Task,Stack Overflow,我想创建大量任务n,并在每个任务I中使用从任务I-1获得的结果 我想到了: class TaskTest { static int count; public static void Main() { int n = 1000000; var t = Add(n); var sum = t.GetAwaiter().GetResult(); Console.WriteLine("sum is: " + sum); } public static Task<

我想创建大量任务n,并在每个任务I中使用从任务I-1获得的结果

我想到了:

class TaskTest
{
static int count;
public static void Main()
{
    int n = 1000000;
    var t = Add(n);
    var sum = t.GetAwaiter().GetResult();
    Console.WriteLine("sum is: " + sum);
}

public static Task<int> Add(int step)
{
    Task t = new Task(() => Add(step));
    t.Start();
    if (step == 0)
        return Task.FromResult(0);
    return Task.FromResult(Add(step - 1).Result + 1);

}

static void AddWithLock(int step)
{
    if (step == 0)
        return;
    Interlocked.Increment(ref count);
    var t = Task.Factory.StartNew(state => AddWithLock(step - 1), CancellationToken.None);
    t.Wait();

}
  }
类任务测试
{
静态整数计数;
公共静态void Main()
{
int n=1000000;
var t=加(n);
var sum=t.GetAwaiter().GetResult();
Console.WriteLine(“总和为:+总和”);
}
公共静态任务添加(int步骤)
{
任务t=新任务(()=>添加(步骤));
t、 Start();
如果(步骤==0)
返回Task.FromResult(0);
返回Task.FromResult(添加(步骤-1).Result+1);
}
静态void AddWithLock(int步)
{
如果(步骤==0)
返回;
联锁增量(参考计数);
var t=Task.Factory.StartNew(state=>AddWithLock(步骤-1),CancellationToken.None);
t、 等待();
}
}
使用Add()方法对较小的n值(如1000)有效,但在n=1 000 000时使用StackOwerFlowException失败

Usin AddWithLock()并不是我想要的(它不使用其他任务的结果),虽然它可以处理大量数据,但速度非常慢

那么,如何修改代码,使其适用于n=100万这样的数字

编辑:

我尝试使用TaskCompletionSource,但仍然得到StackOverflowException

 public static Task<int> Add2(int step)
{
    var tcs = new TaskCompletionSource<int>();

    if (step == 0)
        tcs.SetResult(0);

    else
    {
        var r = Add2(step - 1).Result;
        tcs.SetResult(r + 1);
    }
    return tcs.Task;
}
公共静态任务Add2(int-step)
{
var tcs=new TaskCompletionSource();
如果(步骤==0)
tcs.SetResult(0);
其他的
{
var r=Add2(步骤-1)。结果;
tcs.SetResult(r+1);
}
返回tcs.Task;
}

如果不使用递归,它就足够好了。它在我的PC(旧i7)上完成大约1000毫秒。没有堆栈爆炸

using System;
using System.Diagnostics;
using System.Threading.Tasks;

namespace ManyTasks
{
class Program
{
    public static void Main()
    {
        int n = 1000000;
        Task<int>[] tasks = new Task<int>[n];

        var sw = new Stopwatch();
        sw.Start();
        Task.Factory.StartNew(() =>
        {
            for (int i = 0; i < n; i++)
            {
                int j = i;
                tasks[i] = new Task<int>(() =>
                {
                    if (j == 0)

                        return 1;

                    var result = tasks[j - 1].Result + 1;
                    return result;
                });
                tasks[i].Start();
                tasks[i].Wait();
            }
        }).Wait();

        sw.Stop();
        Console.WriteLine(tasks[n - 1].Result);
        Console.WriteLine($"time: {sw.Elapsed.TotalMilliseconds:0.000}ms");


    }
}
}
使用系统;
使用系统诊断;
使用System.Threading.Tasks;
命名空间多任务
{
班级计划
{
公共静态void Main()
{
int n=1000000;
任务[]任务=新任务[n];
var sw=新秒表();
sw.Start();
Task.Factory.StartNew(()=>
{
对于(int i=0;i
{
如果(j==0)
返回1;
var result=tasks[j-1]。result+1;
返回结果;
});
任务[i].Start();
任务[i]。等待();
}
}).Wait();
sw.Stop();
Console.WriteLine(任务[n-1].Result);
WriteLine($“时间:{sw.appeased.total毫秒:0.000}ms”);
}
}
}

这里有一个递归函数,
Add
调用
Add
它调用
Add
等等。你不能简单地在一百万级的深度上做这件事。我有太多的问题,这段代码无法回答任何问题。例如,为什么要创建任务
t
并启动它?你不用它。此外,
Task.FromResult
不会启动另一个任务,因此实际上您只是递归调用
Add
。首先,提出一个使用任务的合理理由。首先,你的代码可以用普通循环实现,这意味着我想知道你为什么要使用任务。你想解决的实际问题是什么?或者这只是一个学术练习,看看你的堆栈有多大?要让它工作,你需要删除递归。问题不在于任务。目标正如我所说的:创建100万个任务,并在每个任务中使用上一个创建的任务的结果。我不是在试图解决现实世界的问题。我只想在大量任务之间及时传递结果。这个想法来自这里: