Silverlight HttpWebRequest синхронный вызов - PullRequest
4 голосов
/ 04 апреля 2011

В приложении Silverlight я загружаю файл. Я разбиваю файл на куски, а затем загружаю каждый кусок. Проблема в том, что я хочу использовать HttpWebRequest синхронно. Моя задача - убедиться, что все запросы в порядке, и перехватывать исключения. Это возможно в Silverlight? Я хотел бы что-то вроде:

while(chunk)
{
    try{
    HttpWebRequest req = ...
    req.BeginGetRequestStream(new AsyncCallback(WriteCallback), req);
    //add data into request stream
    req.BeginGetResponseStream(new AsyncCallback(ReadCallback), req);
    //parse the response
    chunk = new Chunk();
    }catch(Exception ex)
    {...}
}

Можете ли вы дать мне подсказку, как я могу получить это?

Спасибо, Раду Д

Ответы [ 2 ]

2 голосов
/ 04 апреля 2011

Silverlight не поддерживает синхронные веб-запросы.По этой причине я написал Simple Asynchronous Operation Runner .Одна из целей состоит в том, чтобы иметь возможность писать код, как если бы он был синхронным, затем изменить его для работы с кодом бегуна.

Сначала получите небольшую часть кода для AsyncOperationService из части 1 и добавьте егов ваш проект (не беспокойтесь, если вы найдете статью немного тяжелой, ее не важно использовать на самом деле).

Используя код, который вы уже предоставили как «синхронный шаблон», мы можем увидеть, что нам понадобится параAsyncOperation реализаций для GetRequestStream и GetResponseStream, поэтому мы напишем эти и добавим их в проект: -

public static class WebRequestAsyncOps
{
    public static AsyncOperation GetRequestStreamOp(this WebRequest request, Action<Stream> returnResult)
    {
        return (completed) =>
        {
            request.BeginGetRequestStream((result) =>
            {
                try
                {
                    returnResult(request.EndGetRequestStream(result));
                    completed(null);
                }
                catch (Exception err)
                {
                    completed(err);
                }
            }, null);
        };
    }

    public static AsyncOperation GetResponseOp(this WebRequest request, Action<WebResponse> returnResult)
    {
        return (completed) =>
        {
            request.BeginGetResponse((result) =>
            {
                try
                {
                    returnResult(request.EndGetResponse(result));
                    completed(null);
                }
                catch (Exception err)
                {
                    completed(err);
                }
            }, null);
        };
    }
}

Теперь, если вы загружаете файл по частям, вы, вероятно, захотитечтобы сообщить о прогрессе в пользовательском интерфейсе, поэтому я хотел бы предложить вам также иметь под рукой этот AsyncOperation (внедрить в существующий класс AsyncOperationService): -

    public static AsyncOperation SwitchToUIThread()
    {
        return (completed => Deployment.Current.Dispatcher.BeginInvoke(() => completed(null)));
    }

Теперь мы можем создать асинхронную версию вашего кода: -

 IEnumerable<AsyncOperation> Chunker(Action<double> reportProgress)
 {
     double progress = 0.0;
     Chunk chunk = new Chunk();
     // Setup first chunk;
     while (chunk != null)
     {
          Stream outStream = null;
          HttpWebRequest req = ...

          yield return req.GetRequestStreamOp(s => outStream = s);

          // Do stuff to and then close outStream
          WebResponse response = null;

          yield return req.GetResponseOp(r => response = r);

          // Do stuff with response throw error is need be.
          // Increment progress value as necessary.

          yield return AsyncOperationService.SwitchToUIThread();

          reportProgress(progress);

          chunk = null;
          if (moreNeeded)
          {
             chunk = new Chunk();
             // Set up next chunk;
          }
      }
 }

Наконец, вам просто нужно запустить его и обработать любую ошибку: -

 Chunker.Run((err) =>
 {
     if (err == null)
     {
          // We're done
     }
     else
     {
          // Oops something bad happened.
     }

 });
1 голос
/ 04 апреля 2011

Совершенно неправильно блокировать основной поток пользовательского интерфейса, выполняя функцию Synchronous.

Вы по-прежнему можете загружать большой файл кусками, используя асинхронный механизм.Если вы используете сервис WCF, проверьте этот пост .Я сделал то же самое, используя веб-сервис Soap, работающий на JAXWS, поэтому он не имеет никакого отношения к выбранному вами бэкэнду.

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