Резюме: Возможно ли это?Как я могу заставить HttpWebRequest вести себя как можно синхронно?
unit test function on ui thread:
- creates a background thread
- starts the thread
- waits for it to complete (function does not exit until it completes!)
background thread:
- opens an http stream
- reads a url from the web
- terminates
Мое подозрение: Структура асинхронно помещает результат на некоторую внутреннюю очередь сообщений и, таким образом, обратный вызов ответа никогда не будет называться, пока стек Ui потока не раскручивается и идет к некоторой функции щ нить накачать стек.
Полная история:
Я портирование приложения, которое требует создание потока из различных источников, одна из которых с помощью простого HTTP URL. Я делаю это в фоновом потоке, и в идеале я бы хотел, чтобы он действовал на 100% синхронно, просто блокируйте при необходимости (это нормально, так как он находится в фоновом потоке).
Но кажется, что каркас - это немного мыши-микки, в котором предполагается, что вы будете делать запрос на поток ui, и поэтому он защитит кодера от необходимости создавать фоновый поток для выполнения операции asynch. Но я могу что-то упустить.
Я наткнулся на следующую статью: http://pieterderycke.wordpress.com/2011/05/23/adding-synchronous-methods-to-webrequest-on-windows-phone-7/, , которая предлагает решение для синхронного использования веб-запроса http. Но поскольку это реализовано, я получаю исключение ProtocolViolationException. С тех пор я сделал модификацию кода для использования BeginGetResponse() вместо BeginGetRequestStream(), и это, похоже, больше не вызывает исключение.
Но кажется, что фоновый поток теперь блокируется бесконечно. В моем потоке ui я петлю, делая Thread.Sleep (10), так как я нахожусь в модульной тестовой функции, ожидая, когда мой callback будет вызван. Возможно ли, что обратный вызов не будет вызываться до тех пор, пока функция тестирования единицы не вернется, и нить ui не сможет перекачать сообщения? Если да, то каким-либо образом я могу заставить его перекачивать, чтобы я мог продолжить, где я остановился в процедуре тестирования устройства?
В нижней части статьи, упомянутой выше, делается комментарий: «Если вы протестируете свой код, вы обнаружите, что это взаимоблокировки, если вы выполняете его в потоке пользовательского интерфейса». но я выполняю его на фоновом потоке, так что должно быть хорошо?
В документах msdn показано только, как выполнять асинхронные вызовы. И они также отмечают, что «Метод BeginGetResponse требует выполнения некоторых задач синхронной настройки« ... », как правило, несколько секунд« ... но »может занимать 60 секунд или более». Это звучит довольно плохо, чтобы исполняться на нити ui. http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.begingetresponse.aspx
Пожалуйста, помогите!
Вот мой код:
using System.Net;
using System.Threading;
using System;
using System.IO;
namespace Blah
{
// http://pieterderycke.wordpress.com/2011/05/23/adding-synchronous-methods-to-webrequest-on-windows-phone-7/
// Creates synchronous web requests.
// Must not be called on UI threads.
public static class WebRequestExtensions
{
public static Stream GetRequestStream(this WebRequest request)
{
AutoResetEvent autoResetEvent = new AutoResetEvent(false);
IAsyncResult asyncResult = null;
{
// http://stackoverflow.com/questions/253549/how-do-i-use-httpwebrequest-with-get-method
if (request.Method == "GET")
{
asyncResult = request.BeginGetResponse(
r => autoResetEvent.Set(), null);
}
else
{
asyncResult = request.BeginGetRequestStream(
r => autoResetEvent.Set(), null);
}
}
// Wait until the call is finished
autoResetEvent.WaitOne();
return request.EndGetRequestStream(asyncResult);
}
}
}
Я недавно наткнулся на http://www.eggheadcafe.com/tutorials/aspnet/91f69224-3da5-4959-9901-c5c717c9b184/making-silverlight-emulate-synchronous-requests.aspx, но это показывает ту же проблему. Кажется, что я не получаю свой обратный вызов, пока нить ui не вернет стек ... Я где-то чувствую запах какой-то очереди сообщений фрейма, правильно ли я прав?
Благодарности
Код выглядит хорошо для меня. Я думаю, что ProtocolViolationException вам что-то говорит! Какой URL-адрес вы используете? что было полным сообщением об исключении? – ColinE
Спасибо, но, как я уже сказал, ProtocolViolationException ушел, поскольку я заменил request.BeginGetRequestStream() на request.BeginGetResponse(). – swinefeaster