开发者

Downloading image from web asychrounly in parallel ForEach loop

开发者 https://www.devze.com 2023-02-12 03:27 出处:网络
Hi I would like download images from web asychrounly in parallel loop foreach. I have dictionary with signature IDictionary<string,user>.

Hi I would like download images from web asychrounly in parallel loop foreach.

I have dictionary with signature IDictionary<string,user>. User class has two properties:

Uri ProfilePhoto
BitmapImage ProfilePhotoAsBitmapImage

My aim is, go through dictionary in loop if ProfilePhoto is null I get default avatar, it not I would like download image from web asynchronly.

    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 开发者_StackOverflow中文版is on the bottom
            //of my question
            var image = StartDownloadingImage(f.MediumProfilePhoto);
            image.Freeze();

            f.ProfilePhotoAsBitmap = image;
        });
    }

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.

Start web request:

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

    //how retrieve result of ProcessImage method
}

After web request is finished I call this method:

    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 object is created in ProcessImage method how can I pass this object to the property od User object which is used in GetProfilePhotosFromServer method?

Method above create from MemoryStream BitampImage object.


You need to pass in the additional operations and the UserInfo object as a callback to the asynchronous method. The easiest way to do this is to create a class containing them and pass that as the asynchronous state of the method.

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

精彩评论

暂无评论...
验证码 换一张
取 消