8

I have a console app and I want to launch tasks one after the other.

Here is my code:

static void Main()
{
    string keywords = "Driving Schools,wedding services";
    List<string> kwl = keywords.Split(',').ToList();

    foreach(var kw in kwl)
    {
        Output("SEARCHING FOR: " + kw);
        Task t = new Task(() => Search(kw));
        t.Start();
        t.Wait();
    }

    Console.ReadLine();
}

static async void Search(string keyword)
{
    // code for searching
}

The problem is that it doesn't wait for the first task to finish executing. It fires off the subsequent tasks concurrently.

I am working with a rate limited API so I want to do one after the other.

Why is it not waiting for one search to finish before starting the next search?

Guerrilla
  • 13,375
  • 31
  • 109
  • 210
  • The Search method uses some methods that have to be called asynchronously and I got an error trying to call it normally at first so I tried it this way and it worked. – Guerrilla Jul 07 '16 at 09:43
  • Also understand this behavior is perfect, you are waiting on Task wrapping an Async method, which would have an `await`, which returns and `Task Wait` is done, so you cannot complain – Mrinal Kamboj Jul 07 '16 at 10:17

1 Answers1

18

Your async method just returns void, which means there's no simple way of anything waiting for it to complete. (You should almost always avoid using async void methods. They're really only available for the sake of subscribing to events.) Your task just calls Search, and you're waiting for that "I've called the method" to complete... which it will pretty much immediately.

It's not clear why you're using async at all if you actually want to do things serially, but I'd suggest changing your code to look more like this:

static void Main()
{
    // No risk of deadlock, as a console app doesn't have a synchronization context
    RunSearches().Wait();
    Console.ReadLine();
}

static async Task RunSearches()
{
    string keywords = "Driving Schools,wedding services";
    List<string> kwl = keywords.Split(',').ToList();

    foreach(var kw in kwl)
    {
        Output("SEARCHING FOR: " + kw);
        await Search(kw);
    }             
}

static async Task Search(string keyword)
{
    // code for searching
}
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • In addition async void any exception could terminate the process which is not the behavior of async Task – BRAHIM Kamel Jul 07 '16 at 09:33
  • Thanks! The search function is using some asynchronous functions and I got a bit confused how to start it all off from the main method. I updated my code as you suggested and it works great now! Many thanks Mr. Skeet. – Guerrilla Jul 07 '16 at 09:40
  • @Jon Skeet for Non Console application this shall use `Task.WhenAll` to map the `synchronization` context and avoid `deadlock` ? – Mrinal Kamboj Jul 07 '16 at 10:19
  • @MrinalKamboj: It would depend on exactly what you were doing, but generally you'd just `await` the return value from `RunSearches`. – Jon Skeet Jul 07 '16 at 10:21
  • Look also at [this](http://blog.stephencleary.com/2012/02/async-console-programs.html) article how to introduce an async-compatible context in a console application – Jeroen Heier Jul 08 '16 at 05:11