Используя ожидание внутренних свойств в С#
Возможный дубликат:
Как вызвать метод асинхронизации из получателя или сеттера?
Я пытаюсь реализовать свойство, которое будет использовать Sqlite в нем:
public int ID {
get
{
if (_id != null)
{
return _id;
}
if (string.IsNullOrEmpty(ImageName))
{
return -1;
}
var query = CurrentConnection.Table<Image>().Where(i => i.ImageName == ImageName);
var result = await query.ToListAsync();
...other code
Однако, поскольку свойство не установлено в ожидании (попробовал это, не работает), я не могу использовать ожидание внутри свойства.
Любой способ обойти это, кроме использования метода вместо свойства?
Ответы
Ответ 1
Нет - нет такой вещи, как свойство async. Даже если вы можете объявить свойство async, оно должно быть объявлено как возвращаемое значение Task<int>
, а не int
... в противном случае, что бы вы хотели вернуть, когда вы нажмете выражение await
?
Я бы настоятельно предложил метод GetIdAsync
здесь, предполагая, что вы определенно хотите поведение async.
Ответ 2
Нет никаких технических причин, по которым свойства async
не разрешены в С#. Это было целенаправленное дизайнерское решение, потому что "асинхронные свойства" - оксюморон.
Свойства должны возвращать текущие значения; они не должны запускать фоновые операции.
Обычно, когда кто-то хочет "асинхронное свойство", то, что они действительно хотят, является одним из следующих:
- Асинхронный метод, возвращающий значение. В этом случае измените свойство на метод
async
.
- Значение, которое может использоваться в привязке данных, но должно быть рассчитано/получено асинхронно. В этом случае либо используйте метод
async
factory для содержащего объекта, либо используйте метод async InitAsync()
. Значение, привязанное к данным, будет default(T)
, пока значение не будет рассчитано/получено.
- Значение, которое дорого создавать, но должно быть кэшировано для будущего использования. В этом случае используйте
AsyncLazy
из моего блога или Библиотека AsyncEx. Это даст вам свойство await
.
Ответ 3
Вы не должны использовать свойство Getter для чего-либо, кроме того, что все равно возвращаете значение переменной.
Вызывающий код часто делает предположения о том, чего ожидать при вызове ваших классов.
Правило большого пальца:
- Свойства означают очень быстрый возврат значения
- Методы подразумевают более или менее длительные операции
Поэтому настоятельно рекомендуется не вставлять какую-либо длинную логику в геттер. Вместо этого используйте методы.
Microsoft Rico Mariany дает очень подробную статью об этом здесь: Руководство по эффективности для свойств
Ответ 4
Если вы используете ожидание, вы превращаете остальную часть метода в обратный вызов, что означает, что вы не можете вернуть int. Вам нужно будет вернуть Task <int> . В настоящее время также нет поддержки для использования await в свойстве, вам нужно будет преобразовать свойство в метод get, возвращающий Task <int> .
Если вы хотите вернуть int напрямую, вместо ожидания ждать, используйте awaitable.Result. Это приведет к синхронному разрешению асинхронного действия, позволяя напрямую возвращать конкретный результат.