Проблематично ли запустить задачу в конструкторе? - PullRequest
2 голосов
/ 16 октября 2019

В Вызов асинхронного метода в конструкторе? Вопрос не является ответом, запускает асинхронную операцию в конструкторе и сохраняет Task в элементе и ожидает его перед использованием ресурса:

    public class DeviceAccess
    {
        private readonly Task<Container> containerTask;
        public DeviceAccess(Database database)
        {
            containerTask = GetContainer(database);
        }

        private async Task<Container> GetContainer(Database database)
        {
            var conatinerResponse = await database.CreateContainerIfNotExistsAsync("Device");
            return conatinerResponse.Container;
        }

        public async Task<Device> GetDevice(string deviceId)
        {
            var container = await containerTask;
            return await doSomething(container);
        }
    }

В моем случае каждая операция нуждается в ресурсе, поэтому я не вижу преимущества в использовании отложенной загрузки.

Допустимо ли запускать асинхронную операцию в конструкторе или это может привести к проблемам

1 Ответ

4 голосов
/ 16 октября 2019

Самая большая проблема, которую я вижу здесь, состоит в том, что [Value]Task[<T>] - это API, который включает асинхронность, а не обещание быть асинхронностью;просто потому, что CreateContainerIfNotExistsAsync назван *Async и возвращает Task<T> - что на самом деле не означает, что он асинхронный - он может работать синхронно и возвращать результат через Task.FromResult (он же "асинхронно через синхронизацию)«). Если вы не обеспокоены этой проблемой , тогда я думаю, хорошо. Но мне интересно, был бы более уместным метод OpenAsync(), который вы вызываете после построения , то есть

public class DeviceAccess
{
    private Container _container;
    public DeviceAccess() {}

    public async ValueTask OpenAsync(Database database) {
        if (_container == null)
            _container = await GetContainerAsync(database);
    }

    public async Task<Device> GetDeviceAsync(string deviceId)
    {
        var container = _container ?? throw new InvalidOperationException("not open");
        return await doSomething(container); // might be able to inline the "await" here
    }
}
...