我有一个包含 350 个可下载图片网址的列表。我通过运行多个任务一次并行下载 10 张图像。但是在突然下载了N张图片后,我的代码抛出了以下异常。
异常:“发送请求时发生错误。”
InnerException:“请求被中止:无法创建 SSL/TLS 安全通道。”
StackTrace:“在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务)\r\n 在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)\r\n 在 System.Runtime.CompilerServices.TaskAwaiter`1。获取结果()\r\n ...
我创建了一个示例项目来重现此异常。我手上有2个测试用例。您可以从My Sky Drive Here下载正在运行的测试项目。右键单击文件 HTTPClientTestCases1and2.zip 并下载。
案例 1:使用单个实例 HttpClient 进行所有图像下载。
在这种情况下,我使用相同的 HttpClient 向 10 个 url 发送并行请求。在这种情况下,大部分时间下载是成功的。在最后一次成功下载图像后,等待最少 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 中实现并行下载器的最佳方法是什么。