2013-01-04 32 views
1

我有一個350個可下載圖像URL的列表。通過運行多個任務,我一次下載10張圖像並行。但下載後N圖片數量突然我的代碼拋出以下異常。請求已中止:無法在Windows 8 Metro App中創建SSL/TLS安全通道

例外情況:「發送請求時發生錯誤。」

InnerException:「請求已中止:無法創建SSL/TLS 安全通道。」

堆棧跟蹤:「在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任務 任務)\ r \ n在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任務 任務)\ r \ n在 系統.Runtime.CompilerServices.TaskAwaiter`1.GetResult(個)\ r \ n ...

我創建了一個示例項目重現此異常。我有2個測試案例在我的手。你可以從My Sky Drive Here下載正在運行的測試項目。右鍵單擊文件HTTPClientTestCas es1and2.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中下面的函數檢查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中實現並行下載器的最佳方式是什麼?

+0

假設您的圖片託管在SSL位置是否正確? –

+0

@chuex是的。例如,圖片託管在Facebook或Twitter服務器上。 – Somnath

+0

不幸的是,我沒有一個帶有SSL站點的測試服務器來嘗試你的代碼。如果有幫助,我可以在非SSL測試服務器上運行代碼 - 在此(非SSL)情況下,它工作得很好。 –

回答

2

我跑示例應用程序,而且只在幾個場景中出現錯誤:

  1. 當你的應用程序請求不存在的圖像,在.NET HTTP客戶端拋出異常。你的處理程序並不完全處理這種情況,因爲內部異常是NULL。我不得不調整的代碼一點點:

    async void myImageDownloader_OnFailed(object sender, EventArgs e) 
    { 
        await App.CurrentDispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, delegate 
        { 
         TimeSpan time =(DateTime.Now -dateTimeSuccess); 
    
         String timeGap = "Ideal For:" + time.ToString() + "\n"; 
         ErrorListBox.Text += "\n Failed When: " + DownloadInfo.Text + "\n"; 
         ErrorListBox.Text += timeGap; 
    
         // CX - added null check for InnerException, as these are NULL on HTTP result status 404 
         var ex = sender as Exception; 
         if (ex.InnerException != null) 
          ErrorListBox.Text += ex.InnerException.Message; 
         else 
          ErrorListBox.Text += "Inner Exception null - Outer = (" + ex.ToString() + ")"; 
        }); 
    } 
    
  2. 我收到了你其他錯誤Could not create SSL/TLS secure channel in Windows 8 Metro App唯一的一次,就是當我使用一個HTTP調試代理(提琴手)。如果我不使用Fiddler,攔截所有HTTP(S)調用,那麼我沒有下載問題。我甚至開始快速連續多次下載(通過在一秒鐘內多次點擊藍色下載區域)。結果是所有項目都被下載(除了404錯誤,如上所述)。

下面是成功下載的屏幕截圖(除404s外)。此截圖運行測試用例#2(HttpClient的多個實例)。我確實運行了測試用例#1(HttpClient的單個實例),結果也是成功的。

Test application screenshot

總之,我沒有看到你所遇到的問題。我能想到的唯一的事情就是你可以從不同的機器或位置嘗試你的應用程序。

+0

+1,哪個Url正在拋出異常404?你能分享那個網址嗎?你可以在瀏覽器中試試這個URL,看看它是否拋出404。 – Somnath

+0

@Somnath - 這次我只能得到一個(可能有或沒有其他):https://api.twitter.com/1/users/profile_image ?screen_name = TheKatherineWeb&size =更大我在瀏覽器中嘗試過,找不到它。你真的應該谷歌'Fiddler代理'。這些場景非常方便,因爲它顯示了什麼請求正在製作,哪些請求成功或失敗。 –

相關問題