Ви отримуєте цю помилку, оскільки 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()завдання блокує поточний потік, поки завдання не вирішиться. Це майже ніколи те, що ви хочете, щоб сталося.