none
Problem with Task.Start() RRS feed

  • Question

  • I'm learning async and am trying the following:

    Task<bool>[] tasks = {
                        DataAccess.IsEmailFreeAsync(model.Email),
                        DataAccess.IsUsernameFreeAsync(model.Username) };
    
                    foreach (Task<bool> task in tasks)
                    {
                        task.Start();
                    }
    
                    Task.WaitAll(tasks);

    task.Start() gives the "Start may not be called on a promise-style task"-error.

    I searched online and what I got out of it is that I can't call .Start() because the task is already running, but if I remove the foreach, I can wait 'till eternity... the tasks don't complete. I'm quite sure they are not started.

    I'm I using wrong syntax here?

    Thank you in advance

    Tuesday, November 15, 2016 1:46 PM

Answers

  • You are actually populating your tasks array with the result of calling two methods: DataAccess.IsEmailFreeAsync and DataAccess.IsUsernameFreeAsync.

    In general any asynchronous method you call is going to actually do what it says and return you the task as a 'promise' that it is running and will let you know when it is complete.

    So the error seems right in the sense that it is almost certain that the tasks are already running.

    If Task.WaitAll() is not returning at all, it may be worth digging into the DataAccess methods, as perhaps one of those calls is actually never completing?

    • Marked as answer by DotNetNub Tuesday, November 15, 2016 4:02 PM
    Tuesday, November 15, 2016 2:02 PM

All replies

  • You are actually populating your tasks array with the result of calling two methods: DataAccess.IsEmailFreeAsync and DataAccess.IsUsernameFreeAsync.

    In general any asynchronous method you call is going to actually do what it says and return you the task as a 'promise' that it is running and will let you know when it is complete.

    So the error seems right in the sense that it is almost certain that the tasks are already running.

    If Task.WaitAll() is not returning at all, it may be worth digging into the DataAccess methods, as perhaps one of those calls is actually never completing?

    • Marked as answer by DotNetNub Tuesday, November 15, 2016 4:02 PM
    Tuesday, November 15, 2016 2:02 PM
  • The DataAccess methods are working:

     public static async Task<bool> IsUsernameFreeAsync(string username)
            {
                return await Task.Run(() =>
                {
                    using (TheLandOfPanDbContext ctx = new TheLandOfPanDbContext())
                    {
                        return !ctx.Accounts.Where(a => a.Username == username).Any();
                    }
                });
            }

    I understand that, in my first code block, I am calling the methods, because I use ( ). Is there a way to write this where I don't call them when I put them in the array? I tried some things, but can't seem to get it right.


    • Edited by DotNetNub Tuesday, November 15, 2016 3:02 PM
    Tuesday, November 15, 2016 2:55 PM
  • You could certainly have an array of method delegates rather than call them, but that wouldn't change anything. You would need to call the methods at some point, and the methods themselves would run and return a task putting you back where you started!

    I tried the following Console app and it did complete as expected:

    static void Main(string[] args)
    {
    
         Task<bool>[] tasks = {
                        DummyAsync("Apple"),
                        DummyAsync("Banana") };
    
         Task.WaitAll(tasks);
    
         Console.ReadKey();
    }
    
    
    public static async Task<bool> DummyAsync(string username)
    {
         return await Task.Run(() => true);
    }

    Of course, this is just using a dummy async method that simply returns a Task<bool> with a result of true straight away (and Console apps are not the best way to test async code) . But the point still stands that the general concept works, so it's still looking suspiciously like one of the methods is getting blocked.

    Have you tried it with just one method at a time in your array (instead of both methods)?

    Tuesday, November 15, 2016 3:08 PM
  • I changed Task.WaitAll(tasks); to await Task.WhenAll(tasks); and it works. Don't ask me why.

    Thank you very much. I accept you as answer.

    Tuesday, November 15, 2016 4:02 PM
  • Well I'm glad its working, but be aware that WaitAll and WhenAll are doing two different things!

    Tuesday, November 15, 2016 4:10 PM