For Loop result in Overflow with Task.Run or Task.Start

后端 未结 2 1484
孤独总比滥情好
孤独总比滥情好 2020-12-16 16:53

got a Problem, hope someone can help me out.

i try to start 4 Task in an Loop but im getting an ArgumentOutOfRangeException:

 for (int i = 0; i <          


        
2条回答
  •  陌清茗
    陌清茗 (楼主)
    2020-12-16 17:41

    It's probably caused by a closure problem.

    Try this:

     for (int i = 0; i < 4; i++)
     {
          //start task with current connection
          int index = i;
          tasks[index] = Task.Run(() => GetData(index, plcPool[index]));
     }
    

    What is probably happening is that when the last thread starts running, the loop has already incremented i to 4, and that's the value that gets passed to GetData(). Capturing the value of i into a separate variable index and using that instead should solve that issue.

    As an example, if you try this code:

    public static void Main()
    {
        Console.WriteLine("Starting.");
    
        for (int i = 0; i < 4; ++i)
            Task.Run(() => Console.WriteLine(i));
    
        Console.WriteLine("Finished. Press  to exit.");
        Console.ReadLine();
    }
    

    it will often give you this kind of output:

    Starting.
    Finished. Press  to exit.
    4
    4
    4
    4
    

    Change that code to:

    public static void Main()
    {
        Console.WriteLine("Starting.");
    
        for (int i = 0; i < 4; ++i)
        {
            int j = i;
            Task.Run(() => Console.WriteLine(j));
        }
    
        Console.WriteLine("Finished. Press  to exit.");
        Console.ReadLine();
    }
    

    and you get something like

    Starting.
    Finished. Press  to exit.
    0
    1
    3
    2
    

    Note how it is STILL NOT NECESSARILY IN ORDER! You will see all the correct values printed out, but in an indeterminate order. Multithreading is tricksy!

提交回复
热议问题