1

I have used Task.WaitAll inside an async method in my HomeController, but it is not waiting to complete execution of the async methods. What did I do wrong here? Instead of waiting, it immediately goes to the next statement.

HomeController.cs:

private List<Task> taskList = new List<Task>();

public ActionResult Index()
{
    for (i=0; i<5; i++)
    {
        SendMessages();
    }

    Task.WaitAll(taskList.ToArray());
    // call demo method
}

private async Task SendMessages()
{
    var task = Task.Factory.StartNew(() => ProcessMessages()
    taskList.Add(task);
}

private async Task ProcessMessages()
{
    while (run for 10 minutes)
    {
        // data save
    }
}

I have added a Task into taskList and used Task.WaitAll(taskList.ToArray()); to wait for all tasks to complete, then call demo method. But instead of waiting and executing the whole loop, it immediately goes down after Task.WaitAll(taskList.ToArray()); and executes call demo method. Why is this?

6
  • 2
    Is there another line of private List<Task> taskList = new List<Task>();? The current one defined in Index cannot be accessed to add tasks to by SendMessages. So it looks like you are waiting on an empty list of tasks. Furthermore, you should use await Task.WhenAll instead of the blocking WaitAll Commented Jan 23, 2019 at 18:43
  • sorry taskList it is outside index() Commented Jan 23, 2019 at 18:45
  • @Neo, How are you implementing run for 10 minutes logic in ProcessMessages? Commented Jan 23, 2019 at 18:58
  • var startTime = DateTime.UtcNow; while (DateTime.UtcNow - startTime < TimeSpan.FromMinutes(10)) Commented Jan 23, 2019 at 19:00
  • @Neo, shouldn't the logic to wait for 10 minutes be something like : while((DateTime.UtcNow - startTime).TotalMinutes < 10) . The code that you mentioned is not waiting for 10 minutes and therefore you see that the WaitAll method does not result in 10 minutes wait. Commented Jan 23, 2019 at 19:04

1 Answer 1

2

Task.Factory.StartNew should not be used to launch asynchronous operations, since it does not unwrap the returned Task, and instead returns a new Task that completes as soon as the asynchronous operation launches (or, more precisely, completes its synchronous part). You should use Task.Run instead.

Additionally, SendMessages should not be async. However, Index should be, allowing you to use the asynchronous WhenAll instead of the blocking WaitAll.

private List<Task> taskList = new List<Task>();

public async Task<ActionResult> Index()
{
     for (i = 0; i < 5; i++)
     {
         SendMessages();
     }

     await Task.WhenAll(taskList);
     // call demo method
}

private void SendMessages()
{
    var task = Task.Run(() => ProcessMessagesAsync());   // here
    taskList.Add(task);
}

private async Task ProcessMessagesAsync()
{
    while (run for 10 minutes)
    {
        // data save
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

ok I have made Index async and SendMessages not async now... but why not use waitall and why not SendMessages not async? pls tell me. thanks a lot
WaitAll would block the calling thread until all the tasks have completed, wasting it; whilst WhenAll would relinquish the thread and only resume execution when the tasks have completed. SendMessages does not need to be async since it doesn't have any await.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.