2016-08-27 2 views
0

Я попытался загрузить асинхронно определенные файлы, используя советы от MSDN и отсюда, но мои попытки обычно заканчиваются тупиком или ошибками, вызванными применением, не дожидаясь конца загрузки. Ниже я вставил образец кода, который не работает, но, надеюсь, объясняет мои намерения. Буду признателен за вашу помощь.Загрузите файлы асинхронно, после этого resync

public void SomeMethod() // which must be called synchronously 
    { 
     // Determine which files to download 
    List<FileRequest> fileRequests = Determine(); 

    var test = DownloadFilesAsync(fileRequests); 
    test.Wait(); 

    // After that do something else with downloaded files synchronously 
} 

public async Task DownloadFilesAsync(List<FileRequest> fileRequests) 
    { 
     await Task.WhenAll(fileRequests.Select(fileRequest => 
DownloadFileAsync(fileRequest))).ConfigureAwait(false); 
    } 

public async Task DownloadFileAsync(FileRequest fileRequest) 
    { 
     using (WebClient client = new WebClient()) 
     { 
      await client.DownloadFileTaskAsync(fileRequest.url,fileRequest.downloadPath).ConfigureAwait(false); 
     } 
    } 
+0

Вы смешиваете синхронные и асинхронные, которые, как правило, приводят к тупикам. Является ли 'SomeMethod()' обработчиком событий? – Nkosi

+0

No SomeMethod() не является обработчиком событий и не относится к элементу пользовательского интерфейса (ожидая этого в качестве последующего вопроса). – Tei444

+2

Если этот код запущен в контексте SynchronizationContext, который использует насос сообщений Windows, чтобы выполнить свою магию, тогда он будет блокирован. Вы никогда не должны смешивать async/await с кодом блокировки. –

ответ

1

Использование test.Wait(); блокирует метод ASync

Лучших практик в использовании async заключается в использовании await всего пути через метод. Не смешивайте блокировку и асинхронный код.

public async Task SomeMethod() { 
    // Determine which files to download 
    List<FileRequest> fileRequests = Determine(); 

    //this will allow the down load to not lock the ui 
    await DownloadFilesAsync(fileRequests); 

    // After that do something else with downloaded files synchronously 
    //... 
} 

public async Task DownloadFilesAsync(List<FileRequest> fileRequests) { 
    await Task.WhenAll(fileRequests.Select(fileRequest => 
     DownloadFileAsync(fileRequest))).ConfigureAwait(false); 
} 

public async Task DownloadFileAsync(FileRequest fileRequest) { 
    using (WebClient client = new WebClient()) { 
     await client.DownloadFileTaskAsync(fileRequest.url,fileRequest.downloadPath).ConfigureAwait(false); 
    } 
} 

Источник - Async/Await - Best Practices in Asynchronous Programming

+0

Okey, но теперь SomeMethod() нужно ждать в другом методе, который, в свою очередь, должен быть асинхронным. Таким образом, асинхронные методы будут распространяться, что, в свою очередь, непременно нарушит мои другие методы. Возможно, асинхронный шаблон на основе задач просто не подходит для моего использования? – Tei444

+1

Я использовал другой подход из [link] (http://stackoverflow.com/a/6716310/6757641) – Tei444

+0

Это работает в этом случае, потому что он выполняется в Main. Я считаю, что это единственное исключение из правила. вы прочитали ссылку, которую я включил в ответ. 'Основной метод для консольного приложения - одна из немногих ситуаций, когда код может блокировать асинхронный метод.' – Nkosi

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