none
Tasks are not being excecuted RRS feed

  • Question

  • Hi, 

    It's the first time I am programming tasks, I need to use the same method from different tasks, and as I was having trouble with race conditions (I think it was due to the input data of the method), I implemented this code that waits for the last task to be running before creating a new task to not mix the input data.

    But the problem I have now is that the only task that is being excecuted is the first one and the rest I do not understand why they are not being excecuted.

    This is the code:

    Task[] tasks = new Task[listofGroups.Count()];
            
                foreach (List<Tracker> lot in listofGroups)
                {
      
                    var i = listofGroups.IndexOf(lot);
                    var g = lot;
                    var evaluable = listofTrackers;
                    var groupofTrackers = g;
                    var group = new Group();
                    if (i == 0)
                    {
                        tasks[i] = new Task(() =>
                        {
                            group.StudyGroup(groupofTrackers, evaluable, i, resultspath0);
                        });
                        tasks[i].Start();
                    }
                    else
                    {                   
                        bool st;
                        var status = tasks[i - 1].Status;
                        if(status == TaskStatus.Running || status == TaskStatus.Running || status == TaskStatus.RanToCompletion)
                        {
                            st = true;
                        }
                        else
                        {
                            st = false;
                        }
                        while (tasks[i-1] == null || st == false)
                        {
                            //nothing
                        }
    
                        tasks[i] = new Task(() =>
                        {
                            group.StudyGroup(groupofTrackers, evaluable, i, resultspath0);
                        });
    
                        tasks[i].Start();
    
                    }
                }
    
    
    
                await Task.WhenAll(tasks);

    Tuesday, July 30, 2019 11:36 AM

Answers

  • Hi,

    I'm not sure if I understand your question correctly but:

    You want to execute a list of tasks, but you want to execute them one after the other?

    In that case, you could await each task using the async/await keywords in order to not have to write your own logic for waiting untill completion.

    await Task.Run(() =>
    {
        group.StudyGroup(groupofTrackers, evaluable, i, resultspath0);
    });

    Kind regards,

    Johnny Hooyberghs

    • Marked as answer by Javier Waldo Wednesday, July 31, 2019 2:08 PM
    Tuesday, July 30, 2019 11:45 AM
  • And if you want to run all the tasks together, why not create a class containing all the input for a single Task. Afterwards, foreach through the list of objects and create new tasks with this object as parameter.

    Maybe you could even use a Parallel.ForEach?

    https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/how-to-write-a-simple-parallel-foreach-loop

    • Marked as answer by Javier Waldo Wednesday, July 31, 2019 2:08 PM
    Tuesday, July 30, 2019 11:49 AM
  • > while (tasks[i-1] == null || st == false )

    That loop will never exit.  Once you set "st", its value is never going to change.  I suspect you were expecting the value to change when the task's Status changed, but variables aren't "live" like that.

    (Side note: there's no way for tasks[i-1] to be null.  It would have failed when you fetched the status.)

    I suspect what you meant to say was:

        while( tasks[i-1].Status == TaskStatus.Running )

    However, even that is hugely bad idea, because that's a tight loop that will use up CPU time.  If you want to wait until the task is completed, the you need to block:

        tasks[i-1].Wait();

    However, if you're executing the tasks serially, there's no point in using tasks at all.  If your tasks are using shared state data, then you need to use synchronization to protect that data.  Only you can tell where you need that protection.  When one task you modifies a piece of data that the other tasks need, that's where you need to synchronize.


    Tim Roberts | Driver MVP Emeritus | Providenza &amp; Boekelheide, Inc.

    • Marked as answer by Javier Waldo Wednesday, July 31, 2019 1:55 PM
    Tuesday, July 30, 2019 6:51 PM

All replies

  • Hi,

    I'm not sure if I understand your question correctly but:

    You want to execute a list of tasks, but you want to execute them one after the other?

    In that case, you could await each task using the async/await keywords in order to not have to write your own logic for waiting untill completion.

    await Task.Run(() =>
    {
        group.StudyGroup(groupofTrackers, evaluable, i, resultspath0);
    });

    Kind regards,

    Johnny Hooyberghs

    • Marked as answer by Javier Waldo Wednesday, July 31, 2019 2:08 PM
    Tuesday, July 30, 2019 11:45 AM
  • And if you want to run all the tasks together, why not create a class containing all the input for a single Task. Afterwards, foreach through the list of objects and create new tasks with this object as parameter.

    Maybe you could even use a Parallel.ForEach?

    https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/how-to-write-a-simple-parallel-foreach-loop

    • Marked as answer by Javier Waldo Wednesday, July 31, 2019 2:08 PM
    Tuesday, July 30, 2019 11:49 AM
  • > while (tasks[i-1] == null || st == false )

    That loop will never exit.  Once you set "st", its value is never going to change.  I suspect you were expecting the value to change when the task's Status changed, but variables aren't "live" like that.

    (Side note: there's no way for tasks[i-1] to be null.  It would have failed when you fetched the status.)

    I suspect what you meant to say was:

        while( tasks[i-1].Status == TaskStatus.Running )

    However, even that is hugely bad idea, because that's a tight loop that will use up CPU time.  If you want to wait until the task is completed, the you need to block:

        tasks[i-1].Wait();

    However, if you're executing the tasks serially, there's no point in using tasks at all.  If your tasks are using shared state data, then you need to use synchronization to protect that data.  Only you can tell where you need that protection.  When one task you modifies a piece of data that the other tasks need, that's where you need to synchronize.


    Tim Roberts | Driver MVP Emeritus | Providenza &amp; Boekelheide, Inc.

    • Marked as answer by Javier Waldo Wednesday, July 31, 2019 1:55 PM
    Tuesday, July 30, 2019 6:51 PM