Относно не използването на await при асинхронни методи

+3 гласа
50 прегледа
попитан 2016 март 28 в .NET от Nikoleta.V. (4,090 точки)
етикетиран отново 2016 април 1 от Mitko Vasilev

Работя върху Web API проект, който използва услугите за управляемо кеширане на Azure, за да кешира резултатите от базата данни с цел да се подобри времето за отговор и да се облекчи повтарящ се трафик към базата. Когато опитам да добавя нещо ново в кеша, понякога се хвърля специфичен exception с код DataCacheErrorCode.RetryLater. Естествено, за да опита по-късно без да блокирам метода до направих асинхронен и сложих await Task.Delay за да опита пак след малко. Досега друг разработчик го беше направил с Thread.Sleep, което наистина влияеше върху работата на приложението.

Методът изглежда горе-долу така:

След промяната получавам от всички места където се извиква доскоро синхронния метод Put компилационна грешка:

Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.

В този случай, тъй като Put не връща нищо, според мен е по-добре да се пусне този процес без да ме интересува натам, не виждам причина да блокирам изпълнението на метода,който го извиква. Чудя се дали има някакви опасности или изненади ако позволя на много такива процеси да вървят в background, тъй като Put методът може да се извиква доста често. Или да го await-вам винаги, тъй като в 99% от случаите няма да получа тази грешка и ще се изпълни почти моментално. Искам да съм сигурен, че няма да си навлека проблеми заради изпълнението на прекалено много нишки или нещо подобно.

1 отговор

+1 глас
отговорени 2016 март 29 от valeri.hristov (7,340 точки)
избран 2016 април 5 от Mitko Vasilev
 
Най-добър отговор

Ако има шанс Put да хвърли някакъв друг вид exception по някаква причина, и ти не използваш await Put всеки път, когато слагаш нещо в кеша, exception-ите ще потъват във върнатия Task, който не await-ваш. Ако използваш .NET 4.0, този exception ще се хвърли във Finаlizer частта на този Task. Ако ползваш .NET 4.5, той просто ще бъде игнориран, което може и да не е желателно.

Искам да съм сигурен, че няма да си навлека проблеми заради изпълнението на прекалено много нишки или нещо подобно.

Казвам, за да стане ясно. Когато използваш Task.Delay, не започваш нови нишки. Ползването на Task не винаги значи, че се пускат нови нишки. Конкретно тук, Task.Delay вътрешно използва Timer, така че няма забавяне на нишките(освен нишката, която в момента забавяш ако използваш await ).

...