< p>
public IObservableGetReport(string reportName)
{
return from client in Observable.Return(new WebServiceClient())
from request in Observable. ToAsync(client.GetReportDataAsync)(reportName)
from result in Observable.FromEvent(client, "GetReportDataCompleted").Take(1)
from close in this.CloseClient(client)
select result.EventArgs.Result;
}
I think the problem is due to the web service being called and returning before subscribing to the completed event. I can’t figure out how to get Rx in Subscribe to the event before the asynchronous call. I tried StartWith, but this requires the input and output types to be the same, any ideas?
< p>For example
public IObservableGetReport(string reportName)
{
return from client in Observable.Return(new WebServiceClient())< br /> from completed in Observable.CreateWithDisposable(observer =>
{
var subscription = Observable.FromEvent(client, "GetReportDataCompleted")
.Take(1)
.Select(e => e.EventArgs)
.Subscribe(observer);
client.GetReportDataAsync(reportName);
return subscription;
})
from close in this.CloseClient(client)
select completed.Result;
}
To make this easier to use, I refactored CreateWithDisposable into a All web service calls are used together The public functions, including the automatic determination of the event name from the event args type:
private IObservableCallService (ICommunicationObject serviceClient, Action start) where T: AsyncCompletedEventArgs
{
if (typeof(T) == typeof(AsyncCompletedEventArgs))
{
throw new InvalidOperationException("Event arguments type cannot be used to determine event name, use event name overload instead .");
}
string completedEventName = typeof(T).Name.TrimEnd("EventArgs");
return CallService(serviceClient, start, completedEventName) ;
}
private IObservableCallService (ICommunicationObject serviceClient, Action start, string completedEventName) where T: AsyncCompletedEventArgs
{
return Observable.CreateWithDisposable(observer =>
{
var subscription = Observable.FromEvent(serviceClient, completedEventName).Take(1).Select(e => e.EventArgs).Subscribe(observer) ;
start();
return subscrip tion;
});
}
// Example usage:
public IObservableGetReport(string reportName)
{
return from client in Observable.Return(new WebServiceClient())
from completed in this.CallService(client, () => client.GetReportDataAsync(reportName))
from close in this.CloseClient (client)
select completed.Result;
}
///
/// Asynchronously closes the web service client
// /
/// The web service client to be closed.
///Returns a cold observable sequence of a single success Unit.
private IObservableCloseClient(WebServiceClient client)
{
return this.CallService(client, client.CloseAsync, "CloseCompleted");< br />}
Hope this helps others!
I used Rx to write a simplified Silverlight client library for my WCF web service, but sometimes I noticed that I was missing completed events.
< /p>
public IObservableGetReport(string reportName)
{
return from client in Observable.Return(new WebServiceClient())
from request in Observable.ToAsync(client.GetReportDataAsync)(reportName)
from result in Observable.FromEvent(client, "GetReportDataCompleted").Take(1)
from close in this. CloseClient(client)
select result.EventArgs.Result;
}
I think the problem is due to the web service being called and returning before the subscription has been completed. I can’t figure it out How can I make Rx subscribe to the event before the asynchronous call. I tried StartWith, but this requires the input and output types to be the same, any ideas?
It seems that the best answer is to use Observable.CreateWithDisposable()
For example
p>
public IObservableGetReport(string reportName)
{
return from client in Observable.Return(new WebServiceClient())
from completed in Observable.CreateWithDisposable(observer =>
{
var subscription = Observable.FromEvent(client, "GetReportDataCompleted")
.Take(1)
.Select(e => e. EventArgs)
.Subscribe(observer);
client.GetReportDataAsync(reportName);
return subscription;
})
from close in this.CloseClient(client)< br /> select completed.Result;
}
To make this easier to use, I refactored CreateWithDisposable into a public function that can be used with all my web service calls, including from The event args type automatically determines the event name:
private IOb servableCallService (ICommunicationObject serviceClient, Action start) where T: AsyncCompletedEventArgs
{
if (typeof(T) == typeof(AsyncCompletedEventArgs))
{
throw new InvalidOperationException("Event arguments type cannot be used to determine event name, use event name overload instead.");
}
string completedEventName = typeof(T).Name.TrimEnd( "EventArgs");
return CallService(serviceClient, start, completedEventName);
}
private IObservableCallService (ICommunicationObject serviceClient, Action start , string completedEventName) where T: AsyncCompletedEventArgs
{
return Observable.CreateWithDisposable(observer =>
{
var subscription = Observable.FromEvent(serviceClient, completedEventName ).Take(1).Select(e => e.EventArgs).Subscribe(observer);
start();
return subscription;
});
}< br />
// Example usage:
public IObservableGetReport(string reportName)
{
return from client in Observable.Return(new WebServiceClient())
from completed in this.CallService(client, () => client.GetReportDataAsync(reportName))
from close in this.CloseClient(client)
select completed.Result;
}
/// < summary>
/// Asynchronously closes the web service client
///
/// The web service client to be closed.< /param>
///Returns a cold observable sequence of a single success Unit.
private IObservableCloseClient(WebServiceClient client)
{
return this.CallService(client, client.CloseAsync, "CloseCompleted");
}
Hope this helps others!