我想创建大量任务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();
}
}
使用方法Add()可以将n的较小值(例如1000)工作,但是对于n = 1 000 000则会出现StackOwerFlowException。
Usin AddWithLock()并不是我想要的(它不使用其他任务的结果),并且它在处理大量数字时速度非常慢。
那么我该如何修改适用于n = 1百万等数字的代码?
编辑:
我尝试使用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;
}
答案 0 :(得分:-1)
不使用递归就足够了。它可以在我的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");
}
}
}