Ответ 1
Вы получаете эту ошибку, потому что класс 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");
});
}
Это будет вести себя так, как ожидалось.
Мы могли бы также использовать ключевое слово С# 5.0 await
, чтобы легче добавлять продолжения:
public async Task FunctionA()
{
await Task.Delay(5000);
MessageBox.Show("Waiting Complete");
}
Хотя полное объяснение того, что происходит здесь, выходит за рамки этого вопроса, конечным результатом является метод, который очень похож на предыдущий метод; он отобразит окно сообщения через 5 секунд после вызова метода, но сам метод вернет [почти] сразу в обоих случаях. Тем не менее, await
является очень мощным и позволяет нам писать методы, которые кажутся простыми и понятными, но это было бы намного сложнее и беспорядочно писать, используя ContinueWith
напрямую. Это также значительно упрощает работу с обработкой ошибок, вынимая много шаблонов.