Жду Task.CompletedTask для чего?

Я создал приложение UWP с Windows Template Studio, которое было представлено на Build2017.

Ниже класс является частью сгенерированного кода из него.

public class SampleModelService
{
    public async Task<IEnumerable<SampleModel>> GetDataAsync()
    {
        await Task.CompletedTask; // <-- what is this for?
        var data = new List<SampleModel>();

        data.Add(new SampleModel
        {
            Title = "Lorem ipsum dolor sit 1",
            Description = "Lorem ipsum dolor sit amet",
            Symbol = Symbol.Globe
        });

        data.Add(new SampleModel
        {
            Title = "Lorem ipsum dolor sit 2",
            Description = "Lorem ipsum dolor sit amet",
            Symbol = Symbol.MusicInfo
        });
        return data;
    }
}

У меня вопрос, какова цель и причина await Task.CompletedTask; код здесь? Это на самом деле не имеет Task получатель результата от него.

3 ответа

Решение

Вероятно, просто для того, чтобы на более позднем этапе было проще реализовать вызовы асинхронного кода без необходимости изменять сигнатуру, тем самым предотвращая необходимость рефакторинга вызывающего кода.

Другим вариантом будет удалить async Ключевое слово из сигнатуры метода и этой строки и сделать

return Task.FromResult<IEnumerable<SampleModel>>(data); 

Вы видите эту конструкцию, когда вам нужно вернуть ожидаемую задачу из-за интерфейса, например, в то время как реализация не имеет асинхронной работы.

В этом случае, однако, так как это шаблон, они ожидают, что люди заменят await Task.Completed с чем-то вроде await FetchDataFromDatabaseAsync();, Так как async Ключевое слово уже существует, оно минимизирует необходимые изменения для реализации вашего собственного асинхронного вызова.

В любом случае, без этой ожидающей конструкции вы можете сделать это:

public class SampleModelService
{
    public Task<IEnumerable<SampleModel>> GetDataAsync()
    {
        var data = new List<SampleModel>();

        data.Add(new SampleModel
        {
            Title = "Lorem ipsum dolor sit 1",
            Description = "Lorem ipsum dolor sit amet",
            Symbol = Symbol.Globe
        });

        data.Add(new SampleModel
        {
            Title = "Lorem ipsum dolor sit 2",
            Description = "Lorem ipsum dolor sit amet",
            Symbol = Symbol.MusicInfo
        });

        return Task.FromResult<IEnumerable<SampleModel>>(data); 
     }
}

Если нет необходимости возвращать задачу вообще (у вас нет асинхронного кода), просто удалите ее полностью. (Но тогда вы должны рефакторинг кода, который вызывает этот метод)

Изучая этот код, я подозреваю, что кто-то собирается вызвать асинхронный метод позже в процессе разработки и уже ожидал, что, указав, что этот метод возвращает Task,

await Task.CompletedTask упрощает реализацию этого метода, как сказано в первом ответе, поскольку эта реализация не требует много времени и, следовательно, "await Task.CompletedTask;" или "вернуть Task.FromResult(data);" оба будут работать синхронно. Вы можете использовать эти два шаблона, упомянутых выше, но этот метод разработан как асинхронный, поэтому, когда ваша реализация требует много времени, но не содержит асинхронного кода, используйте Task.Run для создания задачи.

Метод объявлен какasync. Поэтому компилятор ожидает чего-то, например вызова внешней базы данных.

Ваш код синхронный, поэтому компилятор предупредит вас о «запахе кода». Вы можете подавить это предупреждение, добавивawait Task.CompletedTask- который ничего не делает, но компилятор будет доволен.

Это также было бы полезно, если у вас есть условное выражениеawait, например, когда вы проверяете параметры метода или внешняя привязка еще не инициализирована.

Другие вопросы по тегам