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