Я хочу вызвать следующий код:
public async ValueTask UserGivenClaim(AppUser user, Organization org, string claim)
{
var notify = new NotifyClaims(user, org);
await notify.SetReplyToTask(null, org);
await NotificationQueue.PushValueTask(notify);
}
В приведенном выше коде SetReplyToTask()
возвращает Task, а PushValueTask()
возвращает ValueTask. А с точки зрения производительности SetReplyToTask()
в 99% случаев выполняется проверка if, которая является истинной, и возвращается. Таким образом, в 99% случаев внутри него не вызываются методы Task.
Объявление UserGivenClaim
async позволяет мне звонить await notify.SetReplyToTask(null, org);
Будет ли это самый быстрый код? Я беспокоюсь, что упустил преимущество ValueTask, сделав это.
Другая возможность — создать notify.SetReplyToTask()
ValueTask. Если в 99% случаев задача не вызывается, стоит ли мне использовать ValueTask?
await
в ValueTask
возвращающем async
методе не обязательно должны быть одного и того же ожидаемого типа, т. е. только ValueTask
или только Task
. Ваш пример как раз в порядке.
Один из основных моментов использования ValueTask
— это когда асинхронный метод завершится синхронно, как вы отметили:
Если в 99% случаев он не вызывает Задачу, стоит ли мне это делать? используя ValueTask?
Так что если
PushValueTask()
как ValueTask
, мы уверены, что большую часть времени он завершится синхронноSetReplyToTask()
хотя и Task
возвращается, но, согласно вашим словам, в 99% случаев будет выполняться синхронно.большую часть времени будет выполнять UserGivenClaim
синхронно (если только внутри него нет каких-то интересных скрытых зависимостей между двумя вызовами методов).
Тем не менее, в документации перечислены два других «требования», которые должны быть выполнены, прежде чем вы откажетесь от настроек по умолчанию Task
:
Метод может возвращать экземпляр этого типа значения, когда это вероятно. что результат его работы будет доступен синхронно, и когда ожидается, что он будет вызываться так часто, что стоимость выделение новой задачи для каждого вызова будет невозможным.
Вы ничего не упомянули об этих двух (частый вызов, стоимость распределения) для вашего варианта использования, поэтому я думаю, что вы можете излишне переоптимизировать, думая об использовании ValueTask
вместо Task
.
В документации вы можете увидеть множество ограничений, которые ValueTask
имеют, а Task
нет, что делает выбор между ними немного более тонким, чем «Выполняется ли синхронно большую часть времени».
@DavidThielen да. Task
и ValueTask
функционально одинаковы, только если вы await
их. Я не уверен, что вы подразумеваете под «настройкой структуры задач», но я думаю, что вы окажете себе огромную услугу, углубившись в некоторые статьи Стивена Тауба на тему Task
s и async/await
. Они помогут вам построить лучшую ментальную модель и устранить большую часть путаницы, которая естественным образом окружает эту тему — это специально для ValueTask.
Во-первых, спасибо за четкий и полный ответ. Во-вторых, правильно ли будет сказать, что Task и ValueTask функционально одинаковы, но Task всегда устанавливает структуру задачи, а ValueTask устанавливает ее только при необходимости? И поскольку настройка его только в случае необходимости менее эффективна, поэтому я хочу использовать Task, если ему может потребоваться структура задач. ??? ТИА