Используя ожидание внутренних свойств в С#

Возможный дубликат:
Как вызвать метод асинхронизации из получателя или сеттера?

Я пытаюсь реализовать свойство, которое будет использовать 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. Это приведет к синхронному разрешению асинхронного действия, позволяя напрямую возвращать конкретный результат.