繁体   English   中英

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

[英]How to return an object from an async method (c# - 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;            
}

这是异步方法(现在是一个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中传递它时,我需要返回一个位置对象。

我怎样才能做到这一点?

没有其他答案似乎解决了您的代码的主要问题,所以我将添加我的答案。

你有一个异步方法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);
        }
    }
}

您需要从async方法返回Task<T> ,不要让它返回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的返回类型是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;

}

希望能帮助到你!

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;
    }

GetCurrentPosition现在具有返回类型void,因此如果要返回某个类型的值,则应定义返回类型。 因为它也是一个异步函数,GetCurrentPosition的返回类型应该是Task,如下所示:

public async Task<Position> getCurrentPosition() { 
  var position = await locator.GetPositionAsync(timeoutMilliseconds: 10000);
  return position;
}

此外,调用函数应该使用等待如下:

Public PositionPage() {
    Position position = await getCurrentPosition();
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM