Otrzymujesz ten błąd, ponieważ Task
klasa już rozpoczęła zadanie przed przekazaniem go tobie. Powinieneś zawsze wywoływać Start
zadanie, które tworzysz, wywołując jego konstruktor, a nawet nie powinieneś tego robić, chyba że masz ważny powód, aby nie rozpoczynać zadania podczas jego tworzenia; jeśli chcesz, aby zaczął się od razu, użyj Task.Run
lub, Task.Factory.StartNew
aby utworzyć i rozpocząć nowy Task
.
Więc teraz wiemy, jak pozbyć się tego brzydkiego Start
. Uruchomisz swój kod i zauważysz, że okno komunikatu jest wyświetlane od razu, a nie 5 sekund później, o co chodzi?
Cóż, Task.Delay
po prostu daje ci zadanie, które zostanie ukończone za 5 sekund. Nie przerywa wykonywania wątku przez 5 sekund. To, co chcesz zrobić, to mieć kod, który zostanie wykonany po zakończeniu tego zadania. Po to ContinueWith
jest. Pozwala uruchomić kod po wykonaniu danego zadania:
public void FunctionA()
{
Task.Delay(5000)
.ContinueWith(t =>
{
MessageBox.Show("Waiting Complete");
});
}
Będzie to działać zgodnie z oczekiwaniami.
Moglibyśmy również wykorzystać await
słowo kluczowe C # 5.0, aby łatwiej dodawać kontynuacje:
public async Task FunctionA()
{
await Task.Delay(5000);
MessageBox.Show("Waiting Complete");
}
Chociaż pełne wyjaśnienie tego, co się tutaj dzieje, wykracza poza zakres tego pytania, efektem końcowym jest metoda, która zachowuje się bardzo podobnie do poprzedniej metody; pokaże okno komunikatu 5 sekund po wywołaniu metody, ale sama metoda zwróci [prawie] od razu w obu przypadkach. To powiedziawszy, await
jest bardzo potężny i pozwala nam pisać metody, które wydają się proste i nieskomplikowane, ale byłoby o wiele trudniejsze i trudniejsze do napisania ContinueWith
bezpośrednio przy użyciu . Znacznie upraszcza również obsługę błędów, usuwając wiele standardowych kodów.
Wait()
zadania spowoduje zablokowanie bieżącego wątku do czasu rozwiązania zadania. Prawie nigdy tego nie chcesz.