如何从异步方法返回一个对象(c# - xamarin.forms)?

den*_*nno 2 c# asynchronous async-await xamarin xamarin.forms

在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;            
}
Run Code Online (Sandbox Code Playgroud)

这是异步方法(现在是一个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);
    }
}
Run Code Online (Sandbox Code Playgroud)

当我调用getCurrentPosition()在MapSpan中传递它时,我需要返回一个位置对象.

我怎样才能做到这一点?

mac*_*ura 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;
}
Run Code Online (Sandbox Code Playgroud)

你遇到的最大问题是你的构造函数试图调用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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Ehs*_*jad 5

您需要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;

}
Run Code Online (Sandbox Code Playgroud)

在调用方,您还需要async为理想场景创建该方法,但如果您想同步调用异步方法,那么在调用方,它会像:

var position = getCurrentPosition().Result;
// please note that it will be blocking call
// it is synchronously calling the async method
Run Code Online (Sandbox Code Playgroud)

我不知道 的返回类型是什么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;

}
Run Code Online (Sandbox Code Playgroud)

希望能帮助到你!