我有两种方法:
private async Task<GeoCoordinate> CenterMapOnMyLocation()
{
Geolocator myGeolocator = new Geolocator();
Geoposition myGeoposition = await myGeolocator.GetGeopositionAsync();
Geocoordinate myGeocoordinate = myGeoposition.Coordinate;
GeoCoordinate myGeoCoordinate =
ConvertGeocoordinate(myGeocoordinate);
MapCenter = myGeoCoordinate;
if (MyLocation.Latitude == 0 && MyLocation.Longitude == 0)
{
MyLocation = MapCenter;
}
return myGeoCoordinate;
}
和
private void GetClosestLocations(GeoCoordinate myLocation)
{
var locations = new ObservableCollection<PushPinModel>
{
new PushPinModel
{
Location = new GeoCoordinate(51.569593, 10.103504),
LocationName = "1"
},
new PushPinModel
{
Location = new GeoCoordinate(-45.569593, 1.103504),
LocationName = "2"
},
new PushPinModel
{
Location = new GeoCoordinate(0, 0),
LocationName = "3"
}
};
foreach (var location in locations)
{
location.DistanceToMyLocation = HaversineDistance(myLocation, location.Location);
}
Treks = new ObservableCollection<PushPinModel>(locations.OrderBy(l => l.DistanceToMyLocation).Take(2).ToList());
}
在构造函数中我有这样的东西:
public NearbyControlViewModel()
{
var test = CenterMapOnMyLocation();
GetClosestLocations(test);
}
现在,我的问题是,当在构造函数中调用第二个方法时,“test”变量尚未初始化...因为它是异步的。我想要做的是等待它被初始化,然后调用第二种方法。如果我从异步方法调用我的第二个方法,我会得到一个例外:InvalidOperationException - Collection处于不可写模式。 “Treks”值绑定到MapItemsControl。所以我猜这个问题是关于线程的。
答案 0 :(得分:2)
您需要使用异步初始化。我在blog post on async
construction中提供了一些不同的解决方案。
请注意,异步代码强制让您拥有更好的UI设计。即,您必须为UI设计某种“在地图居中之前”状态。 UI最初将在该状态下启动,然后在(异步)初始化完成后,UI将更新。
答案 1 :(得分:1)
如果不是构造函数:
public async Task SomeMethod()
{
var test = await CenterMapOnMyLocation();
GetClosestLocations(test);
}
但是 - 用构造函数?也许只是不这样做。试图在构造函数中等待可能是致命的 - 特别是在某些同步上下文中 - 可能会立即陷入僵局。
考虑在构造函数之后开始。
答案 2 :(得分:0)
您可以在调用GetClosestLocation之前添加test.Wait();
;毕竟,您从CenterMapOnMyLocation获取任务。 (编辑:但实际上,Marc是对的,等待有恶。你应该重构在构造函数之外调用异步代码。)