Вы получаете эту ошибку, потому что Taskкласс уже запустил задачу, прежде чем передать ее вам. Вы должны только когда-либо вызывать Startзадачу, которую вы создаете, вызывая ее конструктор, и вам даже не следует этого делать, если у вас нет веских причин не запускать задачу при ее создании; если вы хотите, чтобы это началось сразу, вы должны использовать Task.Runили Task.Factory.StartNewкак для создания, так и для начала нового Task.
Итак, теперь мы знаем, как просто избавиться от этого надоедливого Start. Вы запустите свой код и обнаружите, что окно сообщения отображается сразу, а не через 5 секунд, что с этим?
Ну Task.Delayпросто дает вам задание, которое будет выполнено за 5 секунд. Он не останавливает выполнение потока на 5 секунд. Что вы хотите сделать, так это иметь некоторый код, который будет выполняться после завершения этой задачи. Вот для чего ContinueWith. Он позволяет запускать некоторый код после выполнения данной задачи:
public void FunctionA()
{
Task.Delay(5000)
.ContinueWith(t =>
{
MessageBox.Show("Waiting Complete");
});
}
Это будет вести себя так, как ожидалось.
Мы также могли бы использовать awaitключевое слово C # 5.0, чтобы упростить добавление продолжений:
public async Task FunctionA()
{
await Task.Delay(5000);
MessageBox.Show("Waiting Complete");
}
Хотя полное объяснение того, что здесь происходит, выходит за рамки этого вопроса, конечным результатом является метод, который ведет себя очень похоже на предыдущий метод; он покажет окно сообщения через 5 секунд после вызова метода, но сам метод вернет [почти] сразу же в обоих случаях. Тем не менее, awaitэто очень мощный инструмент, который позволяет нам писать методы, которые кажутся простыми и понятными, но которые было бы намного сложнее и сложнее писать, используя ContinueWithнапрямую. Это также значительно упрощает обработку ошибок, избавляясь от большого количества шаблонного кода.
Wait()задачи заблокирует текущий поток до тех пор, пока задача не будет решена. Такого почти никогда не бывает.