Chcę utworzyć ukończony Task
(nie Task<T>
). Czy jest coś wbudowanego w .NET, aby to zrobić?
Powiązane pytanie: Utwórz ukończone zadanie <T>
c#
.net
async-await
task-parallel-library
Tarcze Tymoteusza
źródło
źródło
It seems like the answer I'm getting from everyone is that using a garbage value like this is the correct way. That there isn't a way to do this without the garbage value is disappointing -- oh well.
Jak myślisz, jakie to problemy? Jeśli umieścisz w pamięci podręcznej jeden,Task
cały program zajmie dodatkową pamięć. To nic . Poza tym można stworzyć ukończone zadanie bez robienia tego, po prostu nie byłoby lepiej.ValueTask
ukończone zadania (tj. Wartości, które już masz, aby kod był zasadniczo synchroniczny), co pozwoli ci zaoszczędzić przydział.Odpowiedzi:
Najnowsza wersja NET (v4.6) dodaje tylko, że wbudowany Task.CompletedTask :
Ta właściwość jest implementowana jako singleton bez blokady, więc prawie zawsze będziesz używać tego samego ukończonego zadania.
źródło
Task.CompletedTask
wciąż jest wewnętrzny.Task<T>
jest domyślnie konwertowalny naTask
, więc po prostu wypełnij goTask<T>
(dowolnąT
dowolną wartością) i użyj tego. Możesz użyć czegoś takiego, aby ukryć fakt, że gdzieś istnieje rzeczywisty wynik.Pamiętaj, że ponieważ nie ujawniamy wyniku, a zadanie jest zawsze zakończone, możemy buforować pojedyncze zadanie i ponownie je wykorzystać.
Jeśli używasz .NET 4.0, a nie masz go
FromResult
, możesz utworzyć własny, używającTaskCompletionSource
:źródło
Moją preferowaną metodą jest wywołanie
Task.WhenAll()
bez argumentów. Dokumentacja MSDN stwierdza, że „Jeśli dostarczona tablica / wyliczenie nie zawiera żadnych zadań, zwrócone zadanie natychmiast przejdzie w stan RanToCompletion, zanim zostanie zwrócone do programu wywołującego.”. To brzmi jak chcesz.Aktualizacja: Znalazłem źródło w Microsoft Reference Source ; tam widać, że Task.WhenAll zawiera następujące elementy:
Więc Task.CompletedTask jest rzeczywiście wewnętrzny, ale jest ujawniany przez wywołanie WhenAll () bez argumentów.
źródło
Chciałbym użyć
Task.Delay(0)
. Wewnętrznie zwraca buforowaną instancję ukończonejTask<T>
. I tak właśnie sugeruje obecna odpowiedź, tylko teraz nie musisz buforować instancji samodzielnie, ani nie masz żadnych nieeleganckich wartości śmieci w kodzie.Może być myślenie można używać
Task.Yield()
zamiast, ale okazuje się, że rezultatemTask.Yield()
jest nie podtypemTask
, natomiast wynikTask.Delay(0)
jest. To jedna z subtelnych różnic między nimi.źródło
Możesz użyć Task.FromResult (w .NET 4.5), aby zwrócić ukończone
Task<T>
.Jeśli potrzebujesz nie-ogólnego
Task
, zawsze możesz użyćTask.FromResult(0)
lub podobnego, ponieważTask<T>
jest to podklasaTask
.źródło
Do użytku w .Net 4.6 i nowszych
W przypadku niższej wersji możesz użyć
źródło
return Task.Delay(0);
zamiast tego użyć ?Możesz użyć Nito.AsyncEx.TaskConstants.Completed ze wspaniałej biblioteki AsyncEx od Stephen Cleary .
źródło
Co powiesz na:
Możesz pominąć tłumienie ostrzeżeń, jeśli nie masz nic przeciwko.
źródło
async
nadal tworzy cały aparat automatu stanów, nawet jeśli jej nie używasz, więc zwrócenie pustego zadania jest bardziej wydajne w scenariuszach o niskim zużyciu zasobów.