任务库产生随机结果

时间:2015-01-12 03:17:01

标签: c#

我在c#中有关于Task工厂的2个问题。 1)为什么这段代码的结果会随机变化?请注意,如果我单步执行代码,那么它可以工作。 2)如果我改变Div方法抛出异常,那么WaitForAll方法会爆炸。有解决方法吗?

List<Task<float>> tasks = new List<Task<float>>();
for (float i = -3.0f; i < 3.0f; i+=1.0f)
{
    Console.WriteLine("sent " + i);
    Task<float> task = Task.Factory.StartNew<float>(() => Div(5.0f, i));
    tasks.Add(task);
}
Task.WaitAll(tasks.ToArray());
foreach(Task<float> t in tasks)
{
    if (t.IsFaulted)
    {
        Console.WriteLine("Something went wrong: " + t.Exception);
        break; // abort
    }
    else
    {
        Console.WriteLine("result: " + t.Result);
    }
}

private static float Div(float a, float b)
{
    Console.WriteLine("got " + b);
    if (b == 0) return 0.0f;// throw new Exception("Divide by zero");
    return a / b;
}

结果随机变化。以下是其中一项结果:

sent -3
sent -2
sent -1
sent 0
sent 1
sent 2
got 2
got 2
got 2
got 2
got 2
got 3
result: 2.5
result: 1.666667
result: 2.5
result: 2.5
result: 2.5
result: 2.5

1 个答案:

答案 0 :(得分:2)

闭包。

i分配到for循环中的局部变量,然后再将其传递到Task

List<Task<float>> tasks = new List<Task<float>>();
for (float i = -3.0f; i < 3.0f; i+= 1.0f)
{
    float input = i;
    Console.WriteLine("sent " + i);
    Task<float> task = Task.Factory.StartNew<float>(() => Div(5.0f, input));
    tasks.Add(task);
}

否则,i将在循环和所有任务之间共享,因此当循环使用i += 1.0f递增它时,所有任务也会看到更改。这就是为什么你得到一堆2打印出got的原因。