350 個のダウンロード可能な画像 URL のリストがあります。複数のタスクを実行して、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 で。 GetResult()\r\n ...
この例外を再現するサンプル プロジェクトを作成しました。私は2つのテストケースを手にしています。My Sky Drive Hereから実行中のテスト プロジェクトをダウンロードできます。ファイル HTTPClientTestCases1and2.zip を右クリックしてダウンロードします。
ケース 1: すべてのイメージ ダウンロードに 1 つのインスタンス HttpClient を使用する。
この場合、同じ HttpClient を使用して 10 個の URL に並列リクエストを送信しています。この場合、ほとんどの場合、ダウンロードは成功します。イメージのダウンロードが最後に成功した後、次のバッチの次の並列ダウンロード要求を送信するために、最小 40 秒 (最大 1 分 40 秒) 待機します。この例外により、1 つのイメージは確実に失敗します。しかし、非常に多くの場所で、複数のリクエストに対して単一の 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 の次の関数を編集して、2 つのケースを確認してください。
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 で並列ダウンローダーを実装する最良の方法は何ですか。