Я думаю, вы слишком стараетесь смешать код Rx и код не-Rx вместе.Попробуйте заставить ваш код Rx работать в терминах простого запроса Rx, например:
return
from st in fetchRequestStream()
from rp in postDataAndFetchResponse(st)
from s in fetchResult(rp)
select s;
Этот запрос опирается на три функции, которые выглядят следующим образом: Func<X, IObservable<Y>>
.
обрабатывать все повторные попытки и обработку исключений, используя стандартные операторы RX.Нет необходимости делать какие-то «случайные» звонки!
Вы можете назвать это так:
FetchStringFromPost("url", "postData")
.Retry(3)
.Subscribe(s => { }, ex =>
{
/* Exceptions here! */
}, () => { });
Вот полный код:
public IObservable<string> FetchStringFromPost(string WebURL, string postData)
{
var request = (HttpWebRequest)WebRequest.Create(WebURL);
request.ContentType = "application/x-www-form-urlencoded";
request.Method = "POST";
request.Timeout = 100;
request.KeepAlive = false;
request.ProtocolVersion = HttpVersion.Version10;
var fetchRequestStream = Observable
.FromAsyncPattern<Stream>(
request.BeginGetRequestStream,
request.EndGetRequestStream);
var fetchResponse = Observable
.FromAsyncPattern<WebResponse>(
request.BeginGetResponse,
request.EndGetResponse);
Func<Stream, IObservable<HttpWebResponse>> postDataAndFetchResponse = st =>
{
using (var writer = new StreamWriter(st))
{
writer.Write(postData);
}
return fetchResponse().Select(rp => (HttpWebResponse)rp);
};
Func<HttpWebResponse, IObservable<string>> fetchResult = rp =>
{
if (rp.StatusCode == HttpStatusCode.OK)
{
using (var reader = new StreamReader(rp.GetResponseStream()))
{
return Observable.Return<string>(reader.ReadToEnd());
}
}
else
{
var msg = "HttpStatusCode == " + rp.StatusCode.ToString();
var ex = new System.Net.WebException(msg,
WebExceptionStatus.ReceiveFailure);
return Observable.Throw<string>(ex);
}
};
return
from st in fetchRequestStream()
from rp in postDataAndFetchResponse(st)
from s in fetchResult(rp)
select s;
}
Когда я проверялприведенный выше код я попытался позвонить FetchStringFromPost("http://www.microsoft.com", "foo").Materialize()
и получил следующее:
Кажется, работает как удовольствие.Дайте мне знать, как вы идете.