异步方法导致应用程序崩溃

4
我正在创建一个应用程序,从一个返回JSON格式数据的Web服务器请求少量数据,使用Json.net反序列化数据,然后返回一个自定义对象列表。我正在使用一部Android手机调试该应用程序。
接着,使用生成的列表创建了一个listview。与异步方法相比,UI代码似乎可以使用预先创建的对象插入到列表中。异步方法导致了应用程序崩溃。
public partial class Membership : ContentPage
{
    int increment = 1;

    public Membership()
    {
        //begin task
        var task = GetMembers(increment);

        //irrelevant stuff happening

        //wait for task to complete to continue execution
        List<Person> people = task.Result;


        // Create the ListView.
        ListView listView = new ListView
        {

            // Source of data items.
            ItemsSource = people,

            // Define template for displaying each item.
            // (Argument of DataTemplate constructor is called for 
            //      each item; it must return a Cell derivative.)
            ItemTemplate = new DataTemplate(() =>
            {
                // Create views with bindings for displaying each property.
                Label nameLabel = new Label();
                Label statusLabel = new Label();


                nameLabel.SetBinding(Label.TextProperty, "name");
                statusLabel.SetBinding(Label.TextProperty, "status");

                // Return an assembled ViewCell.
                return new ViewCell
                {
                    View = new StackLayout
                    {
                        Padding = new Thickness(0, 5),
                        Orientation = StackOrientation.Horizontal,
                        Children =
                            {
                                //boxView,
                                new StackLayout
                                {
                                    VerticalOptions = LayoutOptions.Center,
                                    Spacing = 0,
                                    Children =
                                    {
                                        nameLabel,
                                        statusLabel
                                    }
                                    }
                            }
                    }
                };
            })
        }; 

        // Build the page.
        this.Content = new StackLayout
        {
            Children =
            {
                header,
                listView
            }
        };


    }

以下是需要翻译的内容:

而需要异步处理的任务:

async Task<List<Person>> GetMembers(int increment)
{
        string jsonString;

        using (var client = new HttpClient())
        {
            //gets the members from the server in json format
            //increment defines which set of members (1-50, 51-100, etc)
            var responseString = await client.GetStringAsync("GENERIC URL" + "increment=" + increment.ToString());
            jsonString = responseString;
        }

        List<Person> memberList = JsonConvert.DeserializeObject<List<Person>>(jsonString);

        return memberList;
}

现在,我已经测试了这段代码,通过绕过异步任务并创建几个预定义的People列表,它可以正常工作。
我知道使用task.Result;方法将阻塞应用程序,直到异步任务完成,但是,在单元测试时速度没有问题,所以我有点困惑。任何帮助都将不胜感激。

2
你有任何错误消息吗?Application Crashing是什么意思?请确保Task.Result可能会导致死锁:https://dev59.com/7WQm5IYBdhLWcg3w6CWr - Sebi
没有错误信息,它只是冻结了。我相信你关于死锁的部分可能是正确的。我将不得不研究完成此任务的替代方法。谢谢。 - BHigzz
1
是的,这是死锁,因为两个线程想要访问相同的上下文。您可以等待调用并将Membership-Method也设置为异步。 - Sebi
1
我将其发布为答案,这样更好记录。 - Sebi
1个回答

3
因为你说:
“没有错误信息,它只是冻结了。”
在评论中,我相信你在这里遇到了死锁情况。关于.Result和.Wait()的问题在这个SO-Ticket中有很好的描述: await works but calling task.Result hangs/deadlocks 你的继续尝试访问一个被.Result阻塞的上下文。你可以像这样重建你的方法:
public async Task InitializeMembership()
{
    //begin task
    var task = GetMembers(increment);

    //irrelevant stuff happening

    //wait for task to complete to continue execution
    List<Person> people = await task;

    //Do further stuff    
}

正如您所看到的,我会使用一个方法而不是构造函数,因为我认为异步构造函数不是最佳实践。希望这能解决您的问题。


你是100%正确的Sebi,我很感激你的帮助。我遇到的主要问题是无法将异步级联到顶层方法Membership,因为它本质上是我的主函数,不能是异步的。将UI代码放入异步InitializeMembership()函数中解决了这个问题。 - BHigzz
@BHigzz 不用谢。请不要忘记将答案标记为已解决;-)。 - Sebi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接