none
Conflito de variáveis usando Task. RRS feed

  • Pergunta

  • Boa Tarde a todos,

    Eu estou aprendendo sobre o Task e me deparo com uma situação o tão quanto duvidosa. Gostaria de saber se existe alguma coisa, que eu possa fazer, para prevenir problemas como este abaixo:

    Eu chamei um Task.Run dentro de um método com uma variável no exterior, só que, quando eu chamo ela, é imprimida 10 ao envés da contagem. 

    Resultado:
    Corredor id 3 começou a correr !
    Corredor id 10 começou a correr !
    Terminei !
    Corredor id 10 começou a correr !
    Corredor id 10 começou a correr !
    Corredor id 10 começou a correr !
    Corredor id 10 começou a correr !
    Corredor id 10 começou a correr !
    Corredor id 10 começou a correr !
    Corredor id 10 começou a correr !
    Corredor id 10 começou a correr !

    Código:

    static void Main(string[] args)
    {
        for(int i = 0; i < 10; i++)
        {
            Task.Run(() => imprimir(i));
        }
    
        Console.WriteLine("Terminei !");
        Console.ReadLine();
    }
    
    public static void imprimir(int corredor)
    {
        Console.WriteLine($"Corredor id {corredor} começou a correr !");
    }
    

    Eu sei se, eu criar uma variável e atribuir a iteração do loop nela, ela funcionaria... mas porque? ... estou fazendo esta pergunta para evitar futuros problemas do gênero.

    for(int i = 0; i < 10; i++)
    {
        // Desta forma funciona, mas porque?
        int varLocal = i;
        Task.Run(() => imprimir(i));
    }


    • Editado KDST domingo, 28 de abril de 2019 17:35 Correção de dados.
    domingo, 28 de abril de 2019 17:32

Respostas

  • KDST,

       O Task.Run é para criar e iniciar uma tarefa em uma única operação de forma assíncrona, isso quer dizer que seu "Corredor ID"  NÃO esperará a conclusão da tarefa para continuar seu processamento, provavelmente por isso que aparece "10", pois ele já chegou ao seu processamento completo.

       Forçando o instanciamento e a inicialização da variável "varLocal" dentro do looping For, a passagem do parâmentro "i" será o valor correto.

       Tente rodar o "Imprimir(i)" SEM o Task.Run para ver o que acontece.

       Pelo que eu entendo, você também pode tentar usar o "Async Await" para que a tarefa não seja concluída antes do "imprimir(i)".

       Por favor, estude um pouco mais sobre "Programação Assíncrona":

    ===========================================

    Programação assíncrona baseada em tarefas

    https://docs.microsoft.com/pt-br/dotnet/standard/parallel-programming/task-based-asynchronous-programming
    ===========================================

    C# - Apresentando TASKS

    http://www.macoratti.net/13/05/c_task1.htm
    ===========================================

    TASK.RUN VS ASYNC AWAIT

    https://www.hexacta.com/2016/06/01/task-run-vs-async-await/

    ===========================================
    Task.Run Etiquette Examples: Don't Use Task.Run in the Implementation

    https://blog.stephencleary.com/2013/11/taskrun-etiquette-examples-dont-use.html
    ===========================================

    []'s,
    Fabio I.
    domingo, 28 de abril de 2019 17:52