Otrzymujesz ten błąd, ponieważ klasa Task
już rozpoczęła zadanie przed podaniem go do ciebie. Powinieneś zawsze wywoływać Start
dla zadania, które tworzysz, wywołując jego konstruktor, a nawet nie powinieneś tego robić, chyba że masz nieodparty powód, aby nie uruchamiać zadania podczas jego tworzenia; Jeśli chcesz rozpocząć od razu, powinieneś użyć Task.Run
lub Task.Factory.StartNew
do utworzenia i uruchomienia nowego Task
.
Więc, teraz wiemy, aby po prostu pozbyć się tego brzydkiego Start
. Uruchomisz swój kod i zobaczysz, że okno wiadomości jest wyświetlane od razu, a nie 5 sekund później, o co chodzi?
Cóż, Task.Delay
wystarczy, że wykonasz zadanie, które zakończy się za 5 sekund. Nie zatrzymuje on wykonywania wątku przez 5 sekund. To, co chcesz zrobić, to mieć kod, który zostanie wykonany po zakończeniu tego zadania. Po to jest ContinueWith
. Pozwala uruchomić kod po wykonaniu zadania:
public void FunctionA()
{
Task.Delay(5000)
.ContinueWith(t =>
{
MessageBox.Show("Waiting Complete");
});
}
To będzie działać zgodnie z oczekiwaniami.
Możemy również wykorzystać C# 5.0 w await
słowa kluczowego łatwiej dodać kontynuacje:
public async Task FunctionA()
{
await Task.Delay(5000);
MessageBox.Show("Waiting Complete");
}
Chociaż pełne wyjaśnienie tego, co się tutaj dzieje jest poza zakresem tego pytania, wynik końcowy jest metoda który zachowuje się bardzo podobnie do poprzedniej metody; pokaże to okno komunikatu 5 sekund po wywołaniu metody, ale sama metoda natychmiast wróci [prawie] w obu przypadkach. To powiedziawszy, await
jest bardzo potężny i pozwala nam pisać metody, które wydają się proste i proste, ale byłoby to o wiele trudniejsze i bardziej niepisane do napisania bezpośrednio przy użyciu ContinueWith
. To także znacznie upraszcza obsługę błędów, zabierając dużo kodu standardowego.
Wywołanie 'Wait()' na zadaniu zablokuje bieżący wątek do momentu rozwiązania zadania. To prawie nigdy nie jest tak, jak chcesz. – Jeremy
@Jeremy: Rzeczywiście, warto zwrócić uwagę na zachowanie, o którym wspomniałeś, ale w tym przypadku jego FunctionA już blokuje bieżący wątek, więc założyłem, że szuka sposobu, aby ustalić, kiedy zadanie zostało zakończone. Aby wyjaśnić różnicę między Wait i async (dla przyszłych czytelników) przeczytaj ten link (http://stackoverflow.com/questions/9519414/whats-the-difference-between-task-start-wait-and-async- czekać na) – Sergiu