user1438082
user1438082

Reputation: 2748

task completion

I have a loop that creates multiple tasks as shown below. How do I update the screen (add a new line to a textbox with some data) as each task completes?

How do I detect when all tasks are complete?

C# Code

 for (int i = 0; i < int.Parse(radTextBoxFloodRequests.Text); i++)
 {
      int x = i;
      // Create a task and supply a user delegate by using a lambda expression. 
      var taskA = new Task(() => TaskRequest(int.Parse(radTextBoxFirstNumber.Text), int.Parse(radTextBoxSecondNumber.Text), int.Parse(radTextBoxFloodDelay.Text), x));
      // Start the task.
      taskA.Start();
 }


 private void TaskRequest(int number1, int number2, int delay, int count)
 {
      // Some long running method
 }

Upvotes: 16

Views: 24855

Answers (4)

mattpm
mattpm

Reputation: 1390

Expanding on User 12345678's answer, you could do something like the below.

    private void RunTasks()
    {
        Dictionary<string, string> dict = new Dictionary<string, string>();

        List<Task> tasks = new List<Task>();
        foreach (KeyValuePair<string,string> kvp in dict)
        {
            Console.WriteLine("Executing task " + kvp.Key + " ...");
            Task t = new Task(() => MyMethod(kvp.Key, kvp.Value));
            tasks.Add(t);
            t.Start();
            t.ContinueWith(task => Console.WriteLine(kvp.Key + " completed"));

        }

        Console.WriteLine("Waiting tasks to complete...");
        Task.WaitAll(tasks.ToArray());
        Console.WriteLine("All tasks completed...");
    }

    private void MyMethod(string arg1, string arg2)
    {

    }

Upvotes: 1

User 12345678
User 12345678

Reputation: 7804

You can use ContinueWith():

"Creates a continuation that executes asynchronously when the target Task completes." - MSDN

Task t = new Task(() => Console.WriteLine("")).ContinueWith(task => Console.Writeline("Continue With"), 
                                                            TaskScheduler.FromCurrentSynchronizationContext());

Upvotes: 21

bas
bas

Reputation: 14972

Are you looking for Parallel.ForEach() ?

    [Test]
    public void ParallelTasks()
    {
        var strings = new List<string> {"task1", "task2", "task3"};

        Parallel.ForEach(strings, str => Console.WriteLine(str + "is done"));

        // All your parallel tasks are executed now
    }

Upvotes: 1

Eugen Rieck
Eugen Rieck

Reputation: 65304

I recommend you use a combination of 3 simple constructs:

  • a simple int numActiveTasks, that is incremented with InterlockedIncrement(ref numActiveTasks) on task creation, i.e. immediately before taskA.Start() and decremented with InterlockedDecrement(ref numActiveTasks) at the end of the task, i.e. at the end of the function TaskRequest(...)
  • a ManualResetEvent, that is reset before task start and signalled on task end after the counter decrement
  • a thread, that WaitOne()s on the ManualResetEvent, then reads numActiveTasks

This gives you

  • notfication of single task done
  • notification of all tasks done (numActiveTasks<=0)

The main advantage of this is, that you have souvereignity about on which thread the notification occurs.

Upvotes: 1

Related Questions