在Xamarin.Forms应用程序中,我使用GeoLocator来检索有关我的位置的信息。 该方法是异步的。我必须返回包含位置参数的对象,但我不能。
这是我的类PositionPage
的构造函数public PositionPage()
{
getCurrentPosition();
var map = new Map(
MapSpan.FromCenterAndRadius(
new Position(45.987487, 9.366337), Distance.FromMiles(0.3)))
{
IsShowingUser = true,
HeightRequest = 100,
WidthRequest = 960,
VerticalOptions = LayoutOptions.FillAndExpand
};
var stack = new StackLayout { Spacing = 0 };
stack.Children.Add(map);
Content = stack;
}
这是异步方法(现在是一个void方法):
public async void getCurrentPosition()
{
try
{
var locator = CrossGeolocator.Current;
locator.DesiredAccuracy = 50;
var position = await locator.GetPositionAsync(timeoutMilliseconds: 10000);
Debug.WriteLine("Position Status: {0}", position.Timestamp);
Debug.WriteLine("Position Latitude: {0}", position.Latitude);
Debug.WriteLine("Position Longitude: {0}", position.Longitude);
}
catch (Exception ex)
{
Debug.WriteLine("Unable to get location, may need to increase timeout: " + ex);
}
}
当我调用getCurrentPosition()在MapSpan中传递它时,我需要返回一个位置对象。
我该怎么做?
答案 0 :(得分:7)
其他答案似乎都没有解决您的代码的主要问题,因此我将添加我的答案。
您有一个异步方法getCurrentPosition()
。此方法等待呼叫:locator.GetPositionAsync(timeoutMilliseconds: 10000)
。此代码唯一的问题是您没有返回从locator.GetPositionAsync()
获得的结果。您可以通过执行以下操作来解决此问题:
//SomeType needs to be the same type that locator.GetPositionAsync() returns
//Also C# naming conventions say that any async methods should end with "Async",
//obviously not required but it will make your life easier later
public async Task<SomeType> GetCurrentPositionAsync()
{
SomeType position = null;
try
{
var locator = CrossGeolocator.Current;
locator.DesiredAccuracy = 50;
position = await locator.GetPositionAsync(timeoutMilliseconds: 10000);
Debug.WriteLine("Position Status: {0}", position.Timestamp);
Debug.WriteLine("Position Latitude: {0}", position.Latitude);
Debug.WriteLine("Position Longitude: {0}", position.Longitude);
}
catch (Exception ex)
{
Debug.WriteLine("Unable to get location, may need to increase timeout: " + ex);
}
return position;
}
你遇到的最大问题是你的构造函数正在尝试调用async方法,该方法将是一个同步调用,它基本上否定了async / await的好处。
我强烈建议更改此应用程序的设计,以便您利用async / await。它不一定是一个重大变化。您可以实现构造对象并为您返回的静态异步方法,这样您就可以等待该调用。像这样:
public class PositionPage
{
public static async Task<PositionPage> CreateAsync()
{
var position = await GetCurrentPositionAsync();
var map = new Map(
MapSpan.FromCenterAndRadius(
new Position(45.452481, 9.166337),
Distance.FromMiles(0.3)))
{
IsShowingUser = true,
HeightRequest = 100,
WidthRequest = 960,
VerticalOptions = LayoutOptions.FillAndExpand
};
var stack = new StackLayout { Spacing = 0 };
stack.Children.Add(map);
var positionPage= new PositionPage();
positionPage.Content = stack;
return positionPage;
}
private PositionPage()
{
}
//SomeType needs to be the same type that locator.GetPositionAsync() returns
//Also C# naming conventions say that any async methods should end with "Async", obviously not required but it will make your life easier later
public async Task<SomeType> GetCurrentPositionAsync()
{
try
{
var locator = CrossGeolocator.Current;
locator.DesiredAccuracy = 50;
var position = await locator.GetPositionAsync(timeoutMilliseconds: 10000);
Debug.WriteLine("Position Status: {0}", position.Timestamp);
Debug.WriteLine("Position Latitude: {0}", position.Latitude);
Debug.WriteLine("Position Longitude: {0}", position.Longitude);
}
catch (Exception ex)
{
Debug.WriteLine("Unable to get location, may need to increase timeout: " + ex);
}
}
}
答案 1 :(得分:2)
您需要从Task<T>
方法返回async
,不要让它返回void
,您需要重构方法,如:
public async Task<Geoposition> getCurrentPosition()
{
Geoposition position = null;
try
{
var locator = CrossGeolocator.Current;
locator.DesiredAccuracy = 50;
position = await locator.GetPositionAsync(timeoutMilliseconds: 10000);
Debug.WriteLine("Position Status: {0}", position.Timestamp);
Debug.WriteLine("Position Latitude: {0}", position.Latitude);
Debug.WriteLine("Position Longitude: {0}", position.Longitude);
}
catch (Exception ex)
{
Debug.WriteLine("Unable to get location, may need to increase timeout: " + ex);
}
return position;
}
并且在调用方面你还需要为理想场景制作该方法async
,但是如果你想同步调用异步方法,那么在调用方面它就像:
var position = getCurrentPosition().Result;
// please note that it will be blocking call
// it is synchronously calling the async method
我不知道GetLocationAsync
的返回类型是什么,但它会返回Task<T>
,其中T
将是某种特定类型,因此更好的是设置返回类型Task<Geoposition>
的方法,假设它返回Task<Geoposition>
,但您可以将其替换为GetPositionAsync
方法的返回类型。
或者您可能希望保持getCurrentPosition
同步,可以这样做:
public Geoposition getCurrentPosition()
{
Geoposition position = null;
try
{
var locator = CrossGeolocator.Current;
locator.DesiredAccuracy = 50;
position = locator.GetPositionAsync(timeoutMilliseconds: 10000).Result;
Debug.WriteLine("Position Status: {0}", position.Timestamp);
Debug.WriteLine("Position Latitude: {0}", position.Latitude);
Debug.WriteLine("Position Longitude: {0}", position.Longitude);
}
catch (Exception ex)
{
Debug.WriteLine("Unable to get location, may need to increase timeout: " + ex);
}
return position;
}
希望它有所帮助!
答案 2 :(得分:1)
GetPositionAsync
返回Task<Position>
我认为你应该使用
public async Task<Position> getCurrentPosition() {
Position position = null;
try
{
var locator = CrossGeolocator.Current;
locator.DesiredAccuracy = 50;
position = await locator.GetPositionAsync(timeoutMilliseconds: 10000);
Debug.WriteLine("Position Status: {0}", position.Timestamp);
Debug.WriteLine("Position Latitude: {0}", position.Latitude);
Debug.WriteLine("Position Longitude: {0}", position.Longitude);
}
catch (Exception ex)
{
Debug.WriteLine("Unable to get location, may need to increase timeout: " + ex);
}
return position;
}
答案 3 :(得分:-2)
GetCurrentPosition现在有一个返回类型为void,所以如果你想返回某个类型的值,你应该定义返回类型。因为它也是一个异步函数,GetCurrentPosition的返回类型应该是这样的任务:
public async Task<Position> getCurrentPosition() {
var position = await locator.GetPositionAsync(timeoutMilliseconds: 10000);
return position;
}
此外,调用函数应该使用等待:
Public PositionPage() {
Position position = await getCurrentPosition();
}