首页 > 解决方案 > Xamarin Forms 网页调用从不返回结果

问题描述

我有这个代码:

public async Task<List<Template>> GetTemplates(User user)
{
    var postData = new List<KeyValuePair<string, string>>();
    postData.Add(new KeyValuePair<string, string>("un", user.Username));
    postData.Add(new KeyValuePair<string, string>("pw", user.Password));
    var content = new FormUrlEncodedContent(postData);
    var weburl = "myapp.org/get_templates.php";
    var response = await PostResponseTemplates<Template>(weburl, content);

    return response;
}

public async Task<List<Template>> PostResponseTemplates<List>(string weburl, FormUrlEncodedContent content)
{
    var response = await client.PostAsync(weburl, content);
    var json = response.Content.ReadAsStringAsync().Result;
    .......
}

但是网络电话永远不会在此行之后返回结果:var response = await client.PostAsync(weburl, content);.

我究竟做错了什么?

更新

这是我现在调用函数的空白:

public MemeTemplateList()
{
    InitializeComponent();

    LoadTemplateList();
}
private void LoadTemplateList()
{
    var templateList = App.RestService.GetTemplates(App.User);
    ....

如何创建此异步并在页面构造函数中运行它?

标签: c#xamarinxamarin.formsxamarin.androidxamarin.ios

解决方案


混合 async-await 和阻塞调用,如.Result

public async Task<List<Template>> PostResponseTemplates<List>(string weburl, FormUrlEncodedContent content) {
    var response = await client.PostAsync(weburl, content);
    var json = response.Content.ReadAsStringAsync().Result; //<--THIS WILL DEADLOCK

    //...omitted for brevity

可能导致死锁。这就是函数不返回的原因。

删除.Result并使代码一直异步

public async Task<List<Template>> PostResponseTemplates<List>(string weburl, FormUrlEncodedContent content) {
    var response = await client.PostAsync(weburl, content);
    var json = await response.Content.ReadAsStringAsync(); //<--THIS

    //...omitted for brevity

我还建议将函数定义从通用更改

public async Task<List<Template>> PostResponseTemplates(string weburl, FormUrlEncodedContent content) {
    //...
}

由于类型在函数中是已知的

List<Template> response = await PostResponseTemplates(weburl, content);

最后确保在调用堆栈中一切都是异步的

public MemeTemplateList() {
    InitializeComponent();
    //Subscribe to event
    loadingTemplates += onLoadingTemplates;
    //raise the event to load the templates.
    LoadTemplateList();
}

private event EventHandler loadingTemplates = delegate { };

//ASYNC VOID ONLY ALLOWED ON EVENT HANDLER!!!!!!!
private async void onLoadingTemplates(object sender, EventArgs args) {
    List<Template> templateList = await App.RestService.GetTemplates(App.User);

    //....
}

private void LoadTemplateList() {
    loadingTemplates(this, EventArgs.Empty);
}

参考Async/Await - 异步编程的最佳实践


推荐阅读