Страницы

Поиск по вопросам

четверг, 11 июля 2019 г.

Как дожидаться await асинхронно для List, чьи задачи уже запушенны

Начал разбираться с async/await, понял принцип работы, но столкнулся со такой проблемой:
///

/// эмитирует файл для загрузки /// public class LoadingFile { public string FileName { get; set; } public int TimeLoad { get; set; }
public LoadingFile(string fileName, int timeLoad) { FileName = fileName; TimeLoad = timeLoad; } }
В классе ViewModel два списка: Список файлов которые нужно загрузить и список уже загруженных файлов.
#region Constructors
public MainWindowViewModel() { //файлы для загрузки. с разным временем скачивания LoadingFiles = new List { new LoadingFile("1", 2000), new LoadingFile("2", 200), new LoadingFile("3", 2000), new LoadingFile("4", 100), new LoadingFile("5", 50), new LoadingFile("6", 70), new LoadingFile("7", 1000), new LoadingFile("8", 2000)
};
//Загруженные файлы. LoadedFiles = new ObservableCollection(); } #endregion
Команда WPF которая запускает процесс скачки
/// /// команда WPF /// private Command _load; public Command Load { get { return _load ?? (_load= new Command(async () => { try { var tasks = LoadingFiles.Select(file => LoadFileAsync(file)).ToList(); //запустим все задачи асинхронно и сохраним их в списке задач
foreach (var task in tasks) //хоть задачи и выполняются асинхронно но результатов дожидаемся синхронно. { var result = await task; LoadedFiles.Add(result); }
MessageBox.Show("Загрузка завершена"); } catch (Exception ex) { MessageBox.Show(ex.Message); } }));
} }
асинхронная задача по скачиванию.
private async Task LoadFileAsync(LoadingFile file) { var res = await Task.Factory.StartNew(() => { Thread.Sleep(file.TimeLoad); return file; }); return res; }
ИТОГО: хочу добиться параллельного скачивания, т.е. чтобы в список скаченных файлов попадали сначала файлы с малым временем скачивания а не по порядку 1,2,3,4... В моей реализации var result = await task; заставляет обязательно дождаться скачивания первого файла, хотя многие другие файлы с меньшем временем скачивания уже скачаны и помешаются в список мгновенно, после скачки первого. Но мне нужен правильный порядок: т.е. все таски параллельно дожидаются await и когда дождались помешают результат в список.


Ответ

Попробуйте такое:
В UI-коде:
async Task DownloadFileAndShow(LoadingFile f) { var res = await LoadFileAsync(file); LoadedFiles.Add(res); }
И запускайте все эти задачи:
var tasks = LoadingFiles.Select(file => DownloadFileAndShow(file)); await Task.WhenAll(tasks);
Ну или просто упакуйте всё в асинхронную лямбду:
await Task.WhenAll( LoadingFiles.Select( async file => LoadedFiles.Add(await LoadFileAsync(file))));

(это если я правильно понял: вам нужны результаты в порядке загрузки, правильно?)

Комментариев нет:

Отправить комментарий