2011-02-21 17 views
0

こんにちは私は並列ループforeachでウェブasychrounlyから画像をダウンロードしたいと思います。Webからasychrounlyの画像をダウンロードするForEachループ

私は辞書IDictionary<string,user>の辞書を持っています。

Uri ProfilePhoto 
BitmapImage ProfilePhotoAsBitmapImage 

私の目的は、私はデフォルトのアバターを取得ProfilePhotoがnullの場合はループ内で辞書を通過、である、それは私がasynchronlyウェブからのダウンロードの画像をしたいと思いません: Userクラスは、2つのプロパティがあります。

private void GetProfilePhotosFromServer(IEnumerable<UserInfo> friends) 
    { 
     Parallel.ForEach(friends, f => 
     { 
      //get defualt 
      if (f.ProfilePhoto == null) 
       f.ProfilePhotoAsBitmap = CreateDefaultAvatar(f.Sex); 

      //start downloading from web server asynchronly 
      //problem is that I don’t know how retrieve BitmapImage object from 
      //StartDownloading method or method ProcessImage, which is on the bottom 
      //of my question 
      var image = StartDownloadingImage(f.MediumProfilePhoto); 
      image.Freeze(); 

      f.ProfilePhotoAsBitmap = image; 
     }); 
    } 

問題は、私は私の質問の下部にあるStartDownloading法やProcessImage、からのBitmapImageオブジェクトを取得方法がわからないということです。

スタートWeb要求:

private void StartDownloadingImage(Uri imageUri) 
{ 
    _webRequest = WebRequest.Create(imageUri); 
    _webRequest.BeginGetResponse(this.ProcessImage, null); 

    //how retrieve result of ProcessImage method 
} 

Webリクエストが終了した後、私は、このメソッドを呼び出します。

private void ProcessImage(IAsyncResult asyncResult) 
    { 
     var response = _webRequest.EndGetResponse(asyncResult); 

     using (var stream = response.GetResponseStream()) 
     { 
      var buffer = new Byte[response.ContentLength]; 
      int offset = 0, actuallyRead = 0; 
      do 
      { 
       actuallyRead = stream.Read(buffer, offset, buffer.Length - offset); 
       offset += actuallyRead; 
      } 
      while (actuallyRead > 0); 


      var image = new BitmapImage 
      { 
       CreateOptions = BitmapCreateOptions.None, 
       CacheOption = BitmapCacheOption.OnLoad 
      }; 
      image.BeginInit(); 

      image.StreamSource = new MemoryStream(buffer); 

      image.EndInit(); 

      //problem 
      return image; 
     } 

    } 

のBitmapImageオブジェクトが、私は、プロパティODユーザーにこのオブジェクトを渡すことができますどのようにProcessImage方法で作成されますGetProfilePhotosFromServerメソッドで使用されるオブジェクト?

上記のメソッドは、MemoryStream BitampImageオブジェクトから作成します。

答えて

1

追加の操作とUserInfoオブジェクトを非同期メソッドのコールバックとして渡す必要があります。これを行う最も簡単な方法は、それらを含むクラスを作成し、それをメソッドの非同期状態として渡すことです。

private class ImageCallbackState 
{ 
    public UserInfo Friend { get; set; } 
    public Action<UserInfo,BitmapImage> Callback { get; set; } 
} 

private void GetProfilePhotosFromServer(IEnumerable<UserInfo> friends) 
{ 
    Parallel.ForEach(friends, f => 
    { 
     //get defualt 
     if (f.ProfilePhoto == null) 
      f.ProfilePhotoAsBitmap = CreateDefaultAvatar(f.Sex); 

     Action<UserInfo,BitmapImage> action = (u,i) => { 
       i.Freeze(); 
       u.ProfilePhotoAsBitMap = i; 
     }; 
     var state = new ImageCallbackState { Friend = f, Callback = action }; 
     StartDownloadingImage(f.MediumProfilePhoto,state); 

    }); 
} 

private void StartDownloadingImage(Uri imageUri, ImageCallbackState state) 
{ 
    _webRequest = WebRequest.Create(imageUri); 
    _webRequest.BeginGetResponse(this.ProcessImage, state); // pass callback state 
} 

private void ProcessImage(IAsyncResult asyncResult) 
{ 
    var response = _webRequest.EndGetResponse(asyncResult); 

    using (var stream = response.GetResponseStream()) 
    { 
     var buffer = new Byte[response.ContentLength]; 
     int offset = 0, actuallyRead = 0; 
     do 
     { 
      actuallyRead = stream.Read(buffer, offset, buffer.Length - offset); 
      offset += actuallyRead; 
     } 
     while (actuallyRead > 0); 


     var image = new BitmapImage 
     { 
      CreateOptions = BitmapCreateOptions.None, 
      CacheOption = BitmapCacheOption.OnLoad 
     }; 
     image.BeginInit(); 

     image.StreamSource = new MemoryStream(buffer); 

     image.EndInit(); 

     var state = asyncResult.AsyncState as ImageCallbackState 

     state.Callback(state.Friend,image); 
    } 

} 
+0

私は少し混乱しています。私のシナリオでは、WPFアプリケーションのUIコントロールにプロパティProfilePhotoAsBitampをバインドしています。私がappを実行すると、エラーが発生します。DependencyObjectと同じスレッドでDependencySourceを作成する必要があります。私はプロパティのProfilePhotoAsBitmapのオブジェクトがUIスレッドとして別のスレッドで作成されていると思いますが、あなたと私はまた、このオブジェクトのProcessImageメソッドとGetProfilePhotosFromServerでFreezeメソッドを呼び出します。 –

+0

@ジョン - 私はWPFを使用しないので、私はそこに多くの助けになるつもりはないと思う。 – tvanfosson

+0

それは大丈夫です、私はあなたの答えをマークします –

関連する問題