Start may not be called on a promise-style task. exception is coming

You are getting that error because the Task class already started the task before giving it to you. You should only ever call Start on a task that you create by calling its constructor, and you shouldn’t even do that unless you have a compelling reason to not start the task when you create it; if you want it started right away you should use Task.Run or Task.Factory.StartNew to both create and start a new Task.

So, now we know to just get rid of that pesky Start. You’ll run your code and find that the message box is shown right away, not 5 seconds later, what’s up with that?

Well, Task.Delay just gives you a task that will be completed in 5 seconds. It doesn’t stop execution of the thread for 5 seconds. What you want to do is have some code that’s executed after that task finishes. That’s what ContinueWith is for. It lets you run some code after a given task is done:

public void FunctionA()
{
    Task.Delay(5000)
    .ContinueWith(t => 
    {
        MessageBox.Show("Waiting Complete");
    });
}

This will behave as expected.

We could also leverage C# 5.0’s await keyword to add continuations more easily:

public async Task FunctionA()
{
    await Task.Delay(5000);
    MessageBox.Show("Waiting Complete");
}

While a full explanation of what’s going on here is beyond the scope of this question, the end result is a method that behaves very similar to the previous method; it will show a message box 5 seconds after you call the method, but the method itself will return [almost] right away in both cases. That said, await is very powerful, and allows us to write methods that seem simple and straightforward, but that would be much harder and messier to write using ContinueWith directly. It also greatly simplifies dealing with error handling, taking out a lot of boilerplate code.

Leave a Comment