从Xamarin.Android事件处理程序死锁中异步调用WebAPI

时间:2017-08-11 12:51:09

标签: c# asp.net-web-api xamarin.android event-handling async-await

我一直在努力解决这个问题,现在是时候让我在这里提问了。所以,情况就是这样:

我有一个WebAPI,一个Xamarin.Android应用程序和一个IdentityServer4实现。 Xamarin.Android应用程序需要调用WebAPI以获取基于搜索的用户列表。这是通过TextChanged事件处理程序中的异步调用完成的。发生的事情是,当等待对WebAPI的调用时,它永远不会返回,并且在某些时候任务被取消。我已经尝试过使用ConfigureAwait(false),我已经将事件处理程序方法设为async void,我已经在这里阅读了几个关于类似问题的其他问题 - 这些选项都不适用于我。但是这里有一些代码可以让你了解我在做什么:

TextChanged处理程序:

protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);

        SetContentView(Resource.Layout.SearchPeopleLayout);

        this.searchUsersElement = FindViewById<EditText>(Resource.Id.searchUsersField);
        this.usersListElement = FindViewById<ListView>(Resource.Id.usersSearchResult);

        using (var scope = App.Container.BeginLifetimeScope())
        {
            this.apiClient = App.Container.Resolve<IUsersApiClient>();
        }

        this.searchUsersElement.TextChanged += SearchUsersElement_TextChanged;
    }

    public async void SearchUsersElement_TextChanged(object sender, Android.Text.TextChangedEventArgs e)
    {
        var length = e.Start + e.AfterCount;
        if (length <= MinUsernameLength)
        {
            return;
        }

        var searchName = string.Join(string.Empty, e.Text);

        var users = await this.apiClient.GetUsers(searchName, Persistor.ApiClient);

        RunOnUiThread(() =>
        {
            var usersAdapter = new UsersAdapter(this, users.ToList());

            this.usersListElement.Adapter = usersAdapter;
        });
    }

这是UsersApiClient实现:

public async Task<IEnumerable<UserModel>> GetUsers(string username, HttpClient client)
    {
        try
        {
            var content = await client.GetStringAsync($"{apiUrl}/users?name={username}").ConfigureAwait(false);

            var result = JsonConvert.DeserializeObject<IEnumerable<UserModel>>(content);

            return result;
        }
        catch (Exception ex)
        {
            throw ex;
        }

    }

GetStringAsync()调用发生死锁。我测试了它通过Postman进行的调用,它给了我正确的响应。只有我还没有尝试过的东西是实现ITextWatcher接口而不是添加事件处理程序,并且更改代码所以我不使用单独的方法而是使用匿名委托 - 我在某些地方读到可能证明是一个问题。

我真的希望你们中的一些人可以帮我解决这个问题并让我理解如何正确地进行这样的异步调用。

最好的问候。

1 个答案:

答案 0 :(得分:0)

好的,所以我不确定是什么解决了这个问题,但这就是我所做的 - 还有另一个StackOverflow问题,类似的问题是从模拟器卸载应用程序解决了问题在重新部署之前手动完成。我还删除了ConfigureAwait(false)调用。突然之间,一切都在发挥作用。不确定它是如何发生的,但这里是 - 手动卸载应用程序并在没有ConfigureAwait(false)的情况下调用API就可以了。