Você está recebendo esse erro porque a Task
classe já iniciou a tarefa antes de entregá-la a você. Você só deve chamar Start
uma tarefa que cria chamando seu construtor, e nem mesmo deve fazer isso, a menos que tenha um motivo convincente para não iniciar a tarefa ao criá-la; se quiser que ele comece imediatamente, você deve usar Task.Run
ou Task.Factory.StartNew
para criar e iniciar um novo Task
.
Então, agora sabemos apenas nos livrar desse incômodo Start
. Você executará seu código e verá que a caixa de mensagem é exibida imediatamente, não 5 segundos depois, o que há com isso?
Bem, Task.Delay
apenas lhe dá uma tarefa que será concluída em 5 segundos. Ele não para a execução do thread por 5 segundos. O que você deseja fazer é executar algum código após o término da tarefa. É para isso que ContinueWith
serve. Ele permite que você execute alguns códigos após a conclusão de uma determinada tarefa:
public void FunctionA()
{
Task.Delay(5000)
.ContinueWith(t =>
{
MessageBox.Show("Waiting Complete");
});
}
Isso se comportará conforme o esperado.
Também poderíamos aproveitar a await
palavra-chave do C # 5.0 para adicionar continuações mais facilmente:
public async Task FunctionA()
{
await Task.Delay(5000);
MessageBox.Show("Waiting Complete");
}
Embora uma explicação completa do que está acontecendo aqui esteja além do escopo desta pergunta, o resultado final é um método que se comporta de maneira muito semelhante ao método anterior; ele mostrará uma caixa de mensagem 5 segundos após você chamar o método, mas o método em si retornará [quase] imediatamente em ambos os casos. Dito isso, await
é muito poderoso e nos permite escrever métodos que parecem simples e diretos, mas que seriam muito mais difíceis e complicados de escrever usando ContinueWith
diretamente. Ele também simplifica muito o tratamento de erros, retirando muito código clichê.
Wait()
uma tarefa bloqueará o thread atual até que a tarefa seja resolvida. Quase nunca é isso que você quer que aconteça.