3

Я пытаюсь проверить URL-адреса изображений, чтобы узнать, действительно ли они действительны. У меня так много из них, что для выполнения этой задачи требуются часы. Поэтому я решил сделать это асинхронно. Я хотел бы знать, есть ли какие-либо большие различия или преимущества в моем коде, как показано ниже.с использованием Parallel.ForEach с/или async/await

Мои основные функции:

Async Function testUrl_async(ByVal myImageurl As String) As Task(Of Boolean) 

    myHttpResponse = Await myHttpClient.GetAsync(myImageurl) 
    If myHttpResponse.IsSuccessStatusCode Then 
     mySuccess = True 
    Else 
     mySuccess = False 
    End If 

    Return mySuccess 
End Function 

Function testUrl(ByVal myImageurl As String) As Boolean 

    myHttpResponse = myHttpClient.GetAsync(myImageurl) 
    If myHttpResponse.IsSuccessStatusCode Then 
     mySuccess = True 
    Else 
     mySuccess = False 
    End If 

    Return mySuccess 
End Function 

1) с помощью асинхр ждут.

For Each myImage In myImages 
    Dim result=await testUrl_async(myImageUrl).Result 
    'some code     
Next 

2) с использованием параллельного Еогеаспа

Parallel.ForEach(myImages, 
    Sub(myImage) 
     testUrl(pictureComponent.websiteShop.hqpatronen, myImageUrl) 
     'some code 
    End Sub) 

3) с использованием параллельного Еогеаспа и asnyc/ждет

Parallel.ForEach(myImages, 
    Sub(myImage) 
     await testUrl_async(pictureComponent.websiteShop.hqpatronen, myImageUrl) 
    'some code 
    End Sub) 

Третий может быть лучшим решением, но это не позволит мне для звонка Await/Async в пределах ForEach.

Если я использую второй, функция testurl имеет HTTP вызов асинхронной, но не с Await, thereofore он падает с сообщением исключения:

[TaskCanceledException:. Задача была отменена]

на линии, которая вызывает myHttpClient.GetAsync. Я предполагаю, что он выбрасывает это исключение, потому что ForEach закончился, и отмена была запрошена, но httpclient еще не завершил свою работу. Как я могу справиться с этим, если это может быть лучшим решением?

Альтернативно любое другое решение, которое ускоряет мою работу.

+0

Это может быть хорошей задачей для TPL DataFlow, который обеспечивает грубую функциональность Parallel.ForEach с поддержкой асинхронным. –

+0

это новый и поддерживается только 4,5 и более поздними версиями? – batmaci

+1

@batmaci Как и 'async/await', да –

ответ

8

Вы, конечно же, не хотите использовать Parallel.ForEach. Parallel предназначен для распространения алгоритмов с привязкой к процессору по нескольким ядрам, что не даст вам никакой пользы (в вашем сценарии ваш алгоритм не связан с ЦП).

Что вы на самом деле хотите, это параллелизм, а не параллелизм. Асинхронный параллелизм может быть сделан с помощью Task.WhenAll:

Dim tasks = myImages.Select(Function(x) testUrl_async(x)) 
Dim results = Await Task.WhenAll(tasks) 
+0

Есть ли большая разница в производительности (скорости) между моим первым подходом с классикой для каждого и синхронным ожиданием? – batmaci

+0

Я тестировал, и это имеет большое значение. спасибо за вашу помощь :) – batmaci

+0

Можете ли вы любезно заглянуть в мой следующий пост, который действительно связан с этим сообщением? Я не хотел задавать дополнительные вопросы, но я создал новую запись. http://stackoverflow.com/questions/31027885/how-can-i-control-thread-count-when-i-use-task-whenall – batmaci

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