我正在学习使用我正在开发的Silverlight 4应用程序的Rx扩展。我创建了一个示例应用程序来确定流程,我无法让它返回任何内容。 这是主要代码:
private IObservable<Location> GetGPSCoordinates(string Address1)
{
var gsc = new GeocodeServiceClient("BasicHttpBinding_IGeocodeService") as IGeocodeService;
Location returnLocation = new Location();
GeocodeResponse gcResp = new GeocodeResponse();
GeocodeRequest gcr = new GeocodeRequest();
gcr.Credentials = new Credentials();
gcr.Credentials.ApplicationId = APP_ID2;
gcr.Query = Address1;
var myFunc = Observable.FromAsyncPattern<GeocodeRequest, GeocodeResponse>(gsc.BeginGeocode, gsc.EndGeocode);
gcResp = myFunc(gcr) as GeocodeResponse;
if (gcResp.Results.Count > 0 && gcResp.Results[0].Locations.Count > 0)
{
returnLocation = gcResp.Results[0].Locations[0];
}
return returnLocation as IObservable<Location>;
}
gcResp返回null。任何想法或建议将不胜感激。
答案 0 :(得分:1)
您订阅的可观察源是异步的,因此您无法在订阅后立即访问结果。您需要访问订阅中的结果。
更好的是,根本不订阅并简单地撰写回复:
private IObservable<Location> GetGPSCoordinates(string Address1)
{
IGeocodeService gsc =
new GeocodeServiceClient("BasicHttpBinding_IGeocodeService");
Location returnLocation = new Location();
GeocodeResponse gcResp = new GeocodeResponse();
GeocodeRequest gcr = new GeocodeRequest();
gcr.Credentials = new Credentials();
gcr.Credentials.ApplicationId = APP_ID2;
gcr.Query = Address1;
var factory = Observable.FromAsyncPattern<GeocodeRequest, GeocodeResponse>(
gsc.BeginGeocode, gsc.EndGeocode);
return factory(gcr)
.Where(response => response.Results.Count > 0 &&
response.Results[0].Locations.Count > 0)
.Select(response => response.Results[0].Locations[0]);
}
如果您只需要第一个有效值(地址位置不太可能更改),请在.Take(1)
和Where
之间添加Select
。
编辑:如果您想要专门处理未找到的地址,您可以返回结果并让消费者处理它,或者您可以返回例外并提供OnError
订阅时的处理程序。如果你想要做后者,你可以使用SelectMany
:
return factory(gcr)
.SelectMany(response => (response.Results.Count > 0 &&
response.Results[0].Locations.Count > 0)
? Observable.Return(response.Results[0].Locations[0])
: Observable.Throw<Location>(new AddressNotFoundException())
);
答案 1 :(得分:0)
如果您展开myFunc
的类型,您会看到它是Func<GeocodeRequest, IObservable<GeocodeResponse>>
。
Func<GeocodeRequest, IObservable<GeocodeResponse>> myFunc =
Observable.FromAsyncPattern<GeocodeRequest, GeocodeResponse>
(gsc.BeginGeocode, gsc.EndGeocode);
因此,当您致电myFunc(gcr)
时,您的IObservable<GeocodeResponse>
而不是GeocodeResponse
。您的代码myFunc(gcr) as GeocodeResponse
会返回null
,因为广告素材无效。
您需要做的是获取observable的最后一个值或者只是进行订阅。调用.Last()
将阻止。如果您致电.Subscribe(...)
,您的回复将通过回拨线程发送。
试试这个:
gcResp = myFunc(gcr).Last();
让我知道你怎么走。
答案 2 :(得分:0)
理查德(和其他人),
所以我有代码返回位置,我订阅了调用代码。这是(希望)最后一期。当我调用GetGPSCoordinates时,下一个语句立即执行而不等待订阅完成。这是一个按钮OnClick事件处理程序的示例。
Location newLoc = new Location();
GetGPSCoordinates(this.Input.Text).ObserveOnDispatcher().Subscribe(x =>
{
if (x.Results.Count > 0 && x.Results[0].Locations.Count > 0)
{
newLoc = x.Results[0].Locations[0];
Output.Text = "Latitude: " + newLoc.Latitude.ToString() +
", Longtude: " + newLoc.Longitude.ToString();
}
else
{
Output.Text = "Invalid address";
}
});
Output.Text = " Outside of subscribe --- Latitude: " + newLoc.Latitude.ToString() +
", Longtude: " + newLoc.Longitude.ToString();
在Subscribe之外执行的Output.Text赋值在Subscribe完成之前执行并显示零,然后subscribe中的那个显示新的位置信息。
此过程的目的是获取位置信息,然后将其保存在数据库记录中,并在Foreach循环中按顺序处理多个地址。我选择Rx Extensions作为解决方案,以避免异步回调作为编码陷阱的问题。但似乎我已经换了另一个陷阱。
思考,评论和建议?