当前位置: 动力学知识库 > 问答 > 编程问答 >

c# - Multiple asynchronous method calls in a loop Window Phone 7

问题描述:

I have a collection of picture Objects for which I need to download thumbs and pictures files located on dataservise, how can I managed this?

In this method I have loop to call three methods; one to add objects to data base, second to download and save picture thumb and third to download and save picture file the other two is ClientOpenReadCompleted methods.

public bool AddAllPhoto()

{

var amount = App.ViewModel.NewPictures.Count;

for (int i = 0; i < amount; i++)

{

//to add picture to DB

SavePicture(App.ViewModel.NewPictures[i]);

DownloadPicture(NewPictures[i].ID.ToString());

DownloadPictureThumb(NewPictures[i].ID.ToString()));

}

return true;

}

Second;

public void DownloadPictureThumb(string path)

{

string outputString = String.Format("http://" + App.ServerAdress + "/ /Pictures/Thumbs/{0}.jpg", path);

var client = new WebClient();

client.OpenReadCompleted += ClientOpenReadCompleted1;

client.OpenReadAsync(new Uri(outputString));

}

private static void ClientOpenReadCompleted1(object sender, OpenReadCompletedEventArgs e)

{

var resInfo = new StreamResourceInfo(e.Result, null);

var reader = new StreamReader(resInfo.Stream);

byte[] contents;

using (var bReader = new BinaryReader(reader.BaseStream))

{

contents = bReader.ReadBytes((int)reader.BaseStream.Length);

}

var file = IsolatedStorageFile.GetUserStoreForApplication();

var thumbFilePath = String.Format(PicturesThumbsColectionKey + "{0}", PictureDataStoreLocal.ID);

var stream = thumbFile.CreateFile(thumbFilePath);

stream.Write(contents, 0, contents.Length);

stream.Close();

}

And third one

public void DownloadPicture(string path)

{

string outputString = String.Format("http://" + App.ServerAdress + "/Pictures/{0}.jpg", path);

var client = new WebClient();

client.OpenReadCompleted += ClientOpenReadCompleted1;

client.OpenReadAsync(new Uri(outputString));

}

private static void ClientOpenReadCompleted1(object sender, OpenReadCompletedEventArgs e)

{

var resInfo = new StreamResourceInfo(e.Result, null);

var reader = new StreamReader(resInfo.Stream);

byte[] contents;

using (var bReader = new BinaryReader(reader.BaseStream))

{

contents = bReader.ReadBytes((int)reader.BaseStream.Length);

}

var file = IsolatedStorageFile.GetUserStoreForApplication();

IsolatedStorageFileStream stream = file.CreateFile(PictureDataStoreLocal.ID.ToString());

stream.Write(contents, 0, contents.Length);

stream.Close();

}

网友答案:

I assume you want to process the pictures synchronously. If so I would use a wait handle. The easiest way to do this would be to declare a private AutoResetEvent field. The AutoResetEvent is good here because it just lets one thread through and then blocks again automatically.

If you do this you will need to make sure of two things: 1. You do ALL work on a different thread so that when you call WaitOne() you aren't blocking the thread that is supposed to be doing the work. 2. You always reset the wait handle regardless of the outcome of the server calls.

To take care of 1. you just need to update your loop:

m_waitHandle.Reset(); // Make sure the wait handle blocks when WaitOne() is called
for (int i = 0; i < amount; i++) 
{
    // Process on a background thread
    ThreadPool.QueueUserWorkItem((obj) =>
    {
        // Get the current index. This is an anonymous method so if
        // we use 'i' directly we will not necessarily be using the
        // correct index. In our case the wait handle avoids this 
        // problem as the pictures are downloaded one after the other
        // but it's still good practise to NEVER use a loop variable in
        // an anonymous method.
        int index = (int)obj;

        //to add picture to DB   
        SavePicture(App.ViewModel.NewPictures[index]); 

        DownloadPicture(NewPictures[index].ID.ToString()); 
        DownloadPictureThumb(NewPictures[index].ID.ToString()));
    }, i);
    m_waitHandle.WaitOne(); // Wait for processing to finish
} 

For 2. you need to make sure that m_waitHandle.Set() is ALWAYS called when processing is finished.

网友答案:

What I do is send extra parameters to the OpenReadCompleted event using a delegate like so,

someimage.LoadingCompleted += delegate(object sender, EventArgs imge) { someimage_LoadingCompleted(sender, imge, _item, "someimage"); };

and then in someimage_LoadingCompleted I have code within a switch statement.

网友答案:

Here is my solution, not that elegant but working one; If you have any suggestion to improve , please post and I will edit my post.

    EventWaitHandle m_WaitHandle;

    public bool AddAllPhoto()
    {
      var amount = App.ViewModel.NewPictures.Count;
    if (m_WaitHandle!=null)
                m_WaitHandle.Reset();
      for (int i = 0; i < amount; i++)
      {
    {
                    SavePicture(App.ViewModel.NewPictures[i]);
                    ThreadPool.QueueUserWorkItem((obj) =>
        {
            var index = (int)obj;
            DownloadPictureThumb(App.ViewModel.NewPictures[index].ID.ToString());
            DownloadPicture(App.ViewModel.NewPictures[index].ID.ToString());

        },i);
              if (m_WaitHandle != null) m_WaitHandle.WaitOne();
                }

                return true;
            }

public void DownloadPictureThumb(string path)
            {
                string outputString = String.Format("http://" + App.ServerAdress + "/Pictures/Thumbs/{0}.jpg", path);
                var client = new WebClient();
                client.OpenReadCompleted += ClientOpenReadCompleted2;
                client.OpenReadAsync(new Uri(outputString),path);
            }

            private static void ClientOpenReadCompleted2(object sender, OpenReadCompletedEventArgs e)
            {
                var resInfo = new StreamResourceInfo(e.Result, null);
                var reader = new StreamReader(resInfo.Stream);

                byte[] contents;
                using (var bReader = new BinaryReader(reader.BaseStream))
                {
                    contents = bReader.ReadBytes((int)reader.BaseStream.Length);
                }

                var file = IsolatedStorageFile.GetUserStoreForApplication();

                var thumbFilePath = String.Format(PicturesThumbsColectionKey + "{0}", e.UserState as string);

                var stream = file.CreateFile(thumbFilePath);

                stream.Write(contents, 0, contents.Length);
                stream.Close();
            }

public void DownloadPicture(string path)
            {
                string outputString = String.Format("http://" + App.ServerAdress + "/Pictures/{0}.jpg", path);
                var client = new WebClient();
                client.OpenReadCompleted += ClientOpenReadCompleted1;
                client.OpenReadAsync(new Uri(outputString), path);
            }

            private static void ClientOpenReadCompleted1(object sender, OpenReadCompletedEventArgs e)
            {
                var resInfo = new StreamResourceInfo(e.Result, null);
                var reader = new StreamReader(resInfo.Stream);

                byte[] contents;
                using (var bReader = new BinaryReader(reader.BaseStream))
                {
                    contents = bReader.ReadBytes((int)reader.BaseStream.Length);
                }

                var file = IsolatedStorageFile.GetUserStoreForApplication();

                var stream = file.CreateFile(e.UserState as string);


                stream.Write(contents, 0, contents.Length);
                stream.Close();
              }

[Here][1] you will find explanation to how to get the url from WebClient in OpenReadCompleted?
分享给朋友:
您可能感兴趣的文章:
随机阅读: