2012-06-11 57 views
0

首先,我的免責聲明:我是平行noob。我認爲這將是一個簡單的「令人尷尬的平行」問題來解決,但它引發了一個循環。使用WebClient時的Parallel.ForEach錯誤

我試圖從網上並行下載一些照片。原始照片是高分辨率,佔用相當大的空間,所以我將在下載後壓縮它們。

下面的代碼:

private static void DownloadPhotos(ISet<MyPhoto> photos) 
    { 
     List<MyPhoto> failed = new List<MyPhoto>(); 

     DateTime now = DateTime.Now; 
     string folderDayOfYear = now.DayOfYear.ToString(); 
     string folderYear = now.Year.ToString(); 
     string imagesFolder = string.Format("{0}{1}\\{2}\\", ImagePath, folderYear, folderDayOfYear); 

     if (!Directory.Exists(imagesFolder)) 
     { 
      Directory.CreateDirectory(imagesFolder); 
     } 

     Parallel.ForEach(photos, photo => 
     { 
      if (!SavePhotoFile(photo.Url, photo.Duid + ".jpg", imagesFolder)) 
      { 
       failed.Add(photo); 
       Console.WriteLine("adding to failed photos: {0} ", photo.Duid.ToString()); 
      } 
     }); 

     Console.WriteLine(); 
     Console.WriteLine("failed photos count: {0}", failed.Count); 

     RemoveHiResPhotos(string.Format(@"{0}\{1}\{2}", ImagePath, folderYear, folderDayOfYear)); 
    } 


    private static bool SavePhotoFile(string url, string fileName, string imagesFolder) 
    { 
     string fullFileName = imagesFolder + fileName; 
     string originalFileName = fileName.Replace(".jpg", "-original.jpg"); 
     string fullOriginalFileName = imagesFolder + originalFileName; 

     if (!File.Exists(fullFileName)) 
     { 
      using (WebClient webClient = new WebClient()) 
      { 
       try 
       { 
        webClient.DownloadFile(url, fullOriginalFileName); 
       } 
       catch (Exception ex) 
       { 
        Console.WriteLine(); 
        Console.WriteLine("failed to download photo: {0}", fileName); 
        return false; 
       } 
      } 
      CreateStandardResImage(fullOriginalFileName, fullOriginalFileName.Replace("-original.jpg", ".jpg")); 
     } 
     return true; 
    } 

    private static void CreateStandardResImage(string hiResFileName, string stdResFileName) 
    { 
     Image image = Image.FromFile(hiResFileName); 
     Image newImage = image.Resize(1024, 640); 
     newImage.SaveAs(hiResFileName, stdResFileName, 70, ImageFormat.Jpeg); 
    } 

因此,這裏就是事情讓我困惑:每張照片的打SavePhotoFile()方法中的Catch {}塊在webClient.DownloadFile線。該錯誤消息是WebClient請求期間發生的異常,內部細節爲「進程無法訪問文件... -original.jpg,因爲它正在被另一進程使用。」

如果我對這個錯誤沒有足夠的困惑,我會對接下來發生的事情感到困惑。事實證明,如果我忽略該消息並等待,圖像最終會下載並處理。

發生了什麼事?

+0

什麼是DUID?我假設它被傳入fileName參數,它是文件名和唯一的?另外,例外數是否等於列表中的文件數? – brianestey

+0

這是一個標識文件的guid。 – John

+0

不,通過目視觀看輸出文件夾,如果照片文件足夠小,以至於快速加載,那麼這些文件不會被添加到錯誤計數中。 – John

回答

0

好的,所以它出現在我關注的並行性上,我做了一個簡單的錯誤:我假設了一些與我的數據不符的事情。 Brianestey發現了這個問題:Duid並不是唯一的。它應該是唯一的,除了在創建列表的過程中缺少一些代碼。

此修復程序是它添加到MyPhoto類

public override bool Equals(object obj) 
    { 
     if (obj is MyPhoto) 
     { 
      var objPhoto = obj as MyPhoto; 
      if (objPhoto.Duid == this.Duid) 
       return true; 
     } 
     return false; 
    } 

    public override int GetHashCode() 
    { 
     return this.Duid.GetHashCode(); 
    }