2016-11-23 3 views
5

У меня есть метод, который возвращает список <> объекта. Этот метод требует времени.Список <MyObject> не содержит определения для GetAwaiter

private List<MyObject> GetBigList() 
{ 
    ... slow stuff 
} 

Этот метод вызывается из 4 или 5 источников. Итак, я подумал, что попробую использовать async и ждать, пока все будет двигаться, пока этот список будет создан. Я добавил этот метод:

public async Task<List<MyObject>> GetBigListAsync() 
{ 
    var resultsTask = GetBigList(); 
    var resuls = await resultsTask; 
    return resuls; 
} 

Но, на этой линии:

var resuls = await resultsTask; 

Я получаю эту ошибку:

List<MyObject> does not contain a definition for GetAwaiter, and no extension method 'GetAwaiter' accepting a first argument of type List<MyObject> could be found.

Что я упускаю?

+1

Ваш пример кода не показывает использование задачи в метод GetBigList и не помечен как async, и это означает, что результат от этого метода не может быть ожидаемым. –

+0

try async Задача <Список > GetBigList() – Mate

+2

Помните, что ожидание не приводит к синхронной операции в асинхронную операцию. Await подписывает оставшуюся часть текущего метода как продолжение уже существующей асинхронной операции *. Ожидание - это * управление асинхронностью *, а не * создание *. Если вы хотите, чтобы синхронная операция была асинхронной, вам нужно будет выяснить, как это произойдет. –

ответ

9

resultTask - это только что вернувшийся из GetBigList(), так что ничего не произойдет в асинхронном режиме.

Что вы можете сделать, это разгрузить задачу в отдельный поток на ThreadPool с помощью Task.Run и вернуть awaitable Task объекта:

// Bad code 
public Task<List<MyObject>> GetBigListAsync() 
{ 
    return Task.Run(() => GetBigList()); 
} 

Хотя выше примере лучше всего соответствует тому, что вы пытаетесь сделать, это не лучшая практика. Попытайтесь сделать асинхронный асинхронный режим по своему усмотрению или если это действительно не так, оставьте решение о выполнении кода в отдельном потоке вызывающему коду и не скрывайте его в реализации F.e. если вызывающий код уже запускает async, нет причин порождать еще один поток. This article описывает это более подробно.

5

Кажется, вы новичок в ожидании aysnc. Что действительно помогло мне понять, что такое асинхронное ожидание - это аналогия ресторана, данная Эриком Липпертом в this interview.. Найдите где-нибудь посередине асинхронного ожидания.

Здесь он описывает, что если повар должен что-то ждать, вместо того чтобы ничего не делать, он начинает оглядываться, чтобы посмотреть, сможет ли он что-то сделать еще раз.

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

Обычно, читая свой большой список, ваш поток будет очень занят, а не ожиданным. Нельзя сказать, что упорядочить другой поток, чтобы сделать материал, улучшало бы время, необходимое для чтения вашего списка. Рассмотрим измерение обоих методов.

One reason to use async-await, even if it would lengthen the time needed to read the big list, would be to keep the caller (user interface?) responsive.

Чтобы сделать вашу функцию асинхр, вам следует сделать следующее:

  • Объявить функцию асинхронной
  • Вместо TResult возвращения Tast<TResult> и вместо void возвращения Task
  • Если ваши вызовы функций другие функции async, подумайте о возврате возвращаемой задачи вместо await, выполните другие полезные действия, которые вам нужно сделать, и await задача, когда вам нужен результат.
  • Если вы действительно хотите, чтобы другая нить делала занятый материал. звоните

    Task.Run (() => GetBigList())

и ждать, когда вам нужны результаты.

private async Task<List<MyObject>> GetBigListAsync() 
{ 
    var myTask = Task.Run(() => GetBigList()); 
    // your thread is free to do other useful stuff right nw 
    DoOtherUsefulStuff(); 
    // after a while you need the result, await for myTask: 
    List<MyObject> result = await myTask; 

    // you can now use the results of loading: 
    ProcessResult(result); 
    return result; 
} 

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

Другие статьи, которые помогли мне понять асинхронному ждут были - Async await, по очень полезным Стивен Клири, - и немного более продвинутый: Async-Wait best practices

Смежные вопросы