Несколько асинхронных вызовов методов в цикле Window Phone 7 - PullRequest
0 голосов
/ 08 ноября 2011

У меня есть коллекция объектов изображений, для которых мне нужно загрузить файлы превью и изображения, расположенные в dataservise. Как мне это сделать? В этом методе у меня есть цикл для вызова трех методов; один для добавления объектов в базу данных, второй для загрузки и сохранения большого пальца изображения и третий для загрузки и сохранения файла изображения; два других метода ClientOpenReadCompleted.

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;
}

Во-вторых,

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();
}

И третий

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();
}

Ответы [ 3 ]

1 голос
/ 08 ноября 2011

Я предполагаю, что вы хотите обрабатывать изображения синхронно.Если так, я бы использовал ручку ожидания.Самый простой способ сделать это - объявить частное поле AutoResetEvent.AutoResetEvent хорош, потому что он просто пропускает один поток, а затем автоматически блокирует его снова.

Если вы сделаете это, вам нужно будет убедиться в двух вещах: 1. ВСЕ вы работаете в другом потоке, таккогда вы вызываете WaitOne (), вы не блокируете поток, который должен выполнять эту работу.2. Вы всегда сбрасываете дескриптор ожидания независимо от результатов вызовов сервера.

Чтобы позаботиться о 1. вам просто нужно обновить цикл:

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
} 

Для 2. васнеобходимо убедиться, что m_waitHandle.Set () ВСЕГДА вызывается после завершения обработки.

0 голосов
/ 10 ноября 2011

Вот мое решение, не такое элегантное, но рабочее;Если у вас есть предложения по улучшению, пожалуйста, напишите, и я отредактирую свой пост.

    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?
0 голосов
/ 08 ноября 2011

Что я делаю, так это отправляю дополнительные параметры в событие OpenReadCompleted, используя такой делегат, как

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

, а затем в someimage_LoadingCompleted у меня есть код в операторе switch.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...