У меня есть список 350 загружаемых URL-адресов изображений. Я загружаю 10 изображений параллельно одним выстрелом, запуская несколько задач. Но после загрузки N количества изображений внезапно мой код выдает следующее исключение.
Исключение: "Произошла ошибка при отправке запроса".
InnerException: "Запрос был прерван: не удалось создать SSL/TLS безопасный канал".
StackTrace: "at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task задача)\r\n в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task задача)\r\n в System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()\r\n...
Я создал образец проекта, чтобы воспроизвести это исключение. В моей руке у меня 2 теста. Вы можете загрузить текущий тестовый проект из My Sky Drive Here. Щелкните правой кнопкой мыши файл HTTPClientTestCases1and2.zip и загрузите.
Случай 1: использование одного экземпляра HttpClient для загрузки всего изображения.
В этом случае я отправляю параллельный запрос на 10 URL-адресов, используя тот же HttpClient. В этом случае загрузка выполняется в большинстве случаев. После последней успешной загрузки изображения подождите минимум 40 секунд (максимум 1 минута 40 секунд), чтобы отправить следующий запрос параллельной загрузки для следующей партии. Из-за этого исключается одно изображение. Но так много мест написано и предложило использовать один HttpClient для множественного запроса.
public async void DownloadUsingSingleSharedHttpClient(Int32 imageIndex)
{
Uri url = new Uri(ImageURLs[imageIndex]);
UnderDownloadCount++;
try
{
Byte[] contentBytes = null;
try
{
// Exception IS THROWN AT LINE BELOW
HttpResponseMessage response = await _httpClient.GetAsync(url);
contentBytes = await response.Content.ReadAsByteArrayAsync();
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("Download Failed at GetAsync() :" + ex.Message);
throw ex;
}
DownloadedCount++;
if (OnSuccess != null)
OnSuccess(this, new DownloadSuccessEventArgs() { Index = imageIndex, Data = contentBytes });
}
catch (HttpRequestException hre)
{
DownloadFailedCount++;
if (OnFailed != null)
OnFailed(hre, null);
}
catch (TaskCanceledException hre)
{
DownloadFailedCount++;
if (OnFailed != null)
OnFailed(hre, null);
}
catch (Exception e)
{
DownloadFailedCount++;
if (OnFailed != null)
OnFailed(e, null);
}
}
Случай 2: Создание нового экземпляра HttpClient для каждого изображения Загрузка
В этом случае он просто терпит неудачу очень часто из-за того же исключения при одновременном загрузке изображений.
public async void DownloadUsingCreatingHttpClientEveryTime(Int32 imageIndex)
{
Uri url = new Uri(ImageURLs[imageIndex]);
UnderDownloadCount++;
try
{
Byte[] contentBytes = null;
using (HttpClientHandler _handler = new HttpClientHandler())
{
_handler.AllowAutoRedirect = true;
_handler.MaxAutomaticRedirections = 4;
using (HttpClient httpClient = new HttpClient(_handler))
{
httpClient.DefaultRequestHeaders.ExpectContinue = false;
httpClient.DefaultRequestHeaders.Add("Keep-Alive", "false");
try
{
// Exception IS THROWN AT LINE BELOW
contentBytes = await httpClient.GetByteArrayAsync(url.OriginalString);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("Download Failed :" + ex.Message);
throw ex;
}
}
_handler.Dispose();
}
DownloadedCount++;
if (OnSuccess != null)
OnSuccess(this, new DownloadSuccessEventArgs() { Index = imageIndex, Data = contentBytes });
}
catch (HttpRequestException hre)
{
DownloadFailedCount++;
if (OnFailed != null)
OnFailed(hre, null);
}
catch (TaskCanceledException hre)
{
DownloadFailedCount++;
if (OnFailed != null)
OnFailed(hre, null);
}
catch (Exception e)
{
DownloadFailedCount++;
if (OnFailed != null)
OnFailed(e, null);
}
}
Пожалуйста, отредактируйте следующую функцию в MainPage.xaml.cs, чтобы проверить два случая
private void Send10DownloadRequestParallel()
{
for (Int32 index = 0; index < 10; index++)
{
Task.Run(() =>
{
Int32 index1 = rand.Next(0, myImageDownloader.ImageURLs.Count - 1);
UpdateDownloadProgress();
// Case 1: Download Using Single Shared HttpClient
// myImageDownloader.DownloadUsingSingleSharedHttpClient(index1);
// OR
// Case 2: Download Using Creating Http Client Every Time
myImageDownloader.DownloadUsingCreatingHttpClientEveryTime(index1);
});
}
}
Мой вопрос: Что я делаю неправильно? Каков наилучший способ реализации параллельного загрузчика в WinRT, преодолев это исключение.