C#解析如何等待Query返回一个值

时间:2016-01-06 15:30:46

标签: xamarin.ios

我正在尝试从Parse(使用c#的xamarin.ios)检索用户数据。我正在等待使用异步方法。我的挑战是,每当我导航到应用程序中的tableView时,应该填充有问题的用户数据,表格总是空的。

我想等到结果返回后再继续代码的其他部分。我试图使用ContinueWith()函数但是经常遇到构建错误 -

Cannot implicitly convert type 'void' to System.Collections.Generic.IEnumerable<Parse.ParseObject>

我的问题:

  1. 这是等待结果的最好方法吗?
  2. 如何解决构建错误?
  3. 这是我目前的实施:

    public async void retrieveData(string username)
        {
            try
            {
    
                this.requests.ClearRequests();
                refreshed = false;
                var query = ParseObject.GetQuery("Requests").WhereEqualTo("username", username);
    
                IEnumerable<ParseObject> results = await query.FindAsync().ContinueWith(t =>{
    
                    if(results != null)
                    {
                        foreach(ParseObject parseObject in results)
                        {
                            UserRequest request = new UserRequest();
                            request.objectId = parseObject.ObjectId;
                            request.make = parseObject.Get<string> ("item1");
                            request.model = parseObject.Get<string> ("item2");
                            request.year = parseObject.Get<string> ("item3");
                            request.userName = parseObject.Get<string> ("username");
                            this.requests.addRequest (request);
                        }
                        refreshed = true;
                    }
    
    
    
                });
    }
            catch(ParseException e) {
                Console.WriteLine (e.Message + e.StackTrace);
            }
        }
    

2 个答案:

答案 0 :(得分:1)

您不应该需要ContinueWith ...这就是await应该处理的内容。

await等待Task,然后使用正确的返回类型返回结果。 ContinueWith会返回Task,因此您必须从任务中抓取Result才能使其可用。

有关此类事情的更多信息,您可以查看Difference between await and ContinueWith

你可以尝试这样的事情。

public async void retrieveData(string username, )
    {
        try
        {

            this.requests.ClearRequests();
            refreshed = false;
            var query = ParseObject.GetQuery("Requests").WhereEqualTo("username", username);

            IEnumerable<ParseObject> results = await query.FindAsync();

            if(results != null)
            {
                foreach(ParseObject parseObject in results)
                {
                    UserRequest request = new UserRequest();
                    request.objectId = parseObject.ObjectId;
                    request.make = parseObject.Get<string> ("item1");
                    request.model = parseObject.Get<string> ("item2");
                    request.year = parseObject.Get<string> ("item3");
                    request.userName = parseObject.Get<string> ("username");
                    this.requests.addRequest (request);
                }
                refreshed = true;
            }
            //This is your refresh method for your TableView
            this.RefreshTableView();
            //or, if in iOS
            NSNotificationCenter.DefaultCenter.PostNotificationName("resultsRetrieved", null);
        }
        catch(ParseException e) {
            Console.WriteLine (e.Message + e.StackTrace);
        }
    }

要在tableView中显示结果,我建议将tableView的刷新移动到在检索和解析results后同步触发的单独方法。这通过上面的this.RefreshTableView()调用显示。

如果在iOS Xamarinpost,则另一个选项是notification NSNotificationCenter PostNotificationNamethe Xamarin documentation for which is here)。使用上面看到的ViewControllers部分,然后在notificationToken中添加一个您希望依赖于数据的观察者。这样做如下:

制作一个 NSObject notificationToken; 对象:

ViewDidLoad

然后在您的设置方法中(您可以将其置于void Setup () { notificationToken = NSNotificationCenter.DefaultCenter.AddObserver ("resultsRetrieved", RefreshData); } 内):

RefeshData

制作void RefreshData (NSString notifString) { this.tableView.ReloadData(); } 方法:

void Teardown ()
{
    NSNotificationCenter.DefaultCenter.RemoveObserver (notificationToken);
}

然后,确保在拆除课程时丢弃通知观察员

findAll

答案 1 :(得分:0)

我有一个类似的问题,所以开始使用回调。我在Xamarin.Android中使用它们,非常确定它们可以在Xamarin.iOS中使用。

启动任务方法的方法 - 注意我将此类的方法作为参数传递

private async void updatedData()
    {
        await Utils.DataTasks.getNewLiveTips(populateTipsList);
    } 

从服务器调用数据的方法

public class DataTasks
{
    public static async Task getAllData(Action<IEnumerable<ParseObjects>> callback) { 

        var query = new ParseQuery<ParseObjects>().OrderByDescending("updatedAt").Limit(5);
        IEnumerable<ParseObjects> parseTips = await query.FindAsync();

        foreach (var tip in parseTips)
        {
         // Save data to DB if needed 
        }

        callback(parseTips);
    }

我在第一个实例中作为参数传递的方法现在称为

private void populateTipsList(IEnumerable<ParseObjects> results)
    {
        mAdapter = new TipAdapter(this.Activity, results);
        mRecyclerView.SetAdapter(mAdapter);

        refresher.Refreshing = false;
    }