从 Xamarin PCL 调用 REST API 时程序挂起

Posted

技术标签:

【中文标题】从 Xamarin PCL 调用 REST API 时程序挂起【英文标题】:Program hangs when calling REST API from Xamarin PCL 【发布时间】:2016-08-09 23:25:42 【问题描述】:

我的 Xamarin PCL 中有以下代码

    public Product Product(int id)
    

        var product = Get<Product>(endpoint + "?id=" + id).Result;
        return product;
    

    static async Task<T> Get<T>(string endpoint)
    
        using (var client = new HttpClient())
        
            var response = await client.GetAsync(endpoint);
            string content = await response.Content.ReadAsStringAsync();
            return await Task.Run(() => JsonConvert.DeserializeObject<T>(content));
        
    

我的程序就挂在这一行

var response = await client.GetAsync(endpoint);

没有抛出异常。

我在控制台应用程序中执行相同的代码,它运行良好。

我能看到的唯一区别是,在我的控制台应用程序中,我在 lib\net45 文件夹中引用了 Newtonsoft.Json.dll。在我的 Xamarin PCL 项目中,我在 lib\portable-net40+sl5+wp80+win8+wpa81 文件夹中引用了 Newtonsoft.Json.dll。我尝试引用 lib\portable-net45+wp80+win8+wpa81+dnxcore50 文件夹中的 dll,结果相同。

我正在使用 Json 8.0.3

【问题讨论】:

【参考方案1】:

代码挂起,因为您正在访问任务的Result 属性。您应该改用 await 关键字从任务中获取结果。

发生死锁是因为同步上下文被两个不同的线程捕获。有关详细信息,请参阅此答案:await vs Task.Wait - Deadlock?

它在控制台应用程序中有效,因为SynchronizationContext.Current 为空,因此不会发生死锁。更多详情请看这篇文章:Await, SynchronizationContext, and Console Apps

【讨论】:

【参考方案2】:

您正在通过访问 Result 属性强制异步操作​​以同步方法运行

public async Task<Product> Product(int id)


    var product = await Get<Product>(endpoint + "?id=" + id);
    return product;

如上修改产品方法将修复它。

【讨论】:

以上是关于从 Xamarin PCL 调用 REST API 时程序挂起的主要内容,如果未能解决你的问题,请参考以下文章

将文件下载进度从 PCL 更新到 Xamarin.Android

来自 PCL 的 Xamarin WebAPI 调用

Xamarin PCL C# - 将字符串反序列化为 JSONObject/JSONArray

Xamarin PCL 项目中的 HttpClient 访问失败

如何使用 PCL 支持从 xamarin 跨平台项目中的 URL 下载文件

为啥我不能在 Xamarin Forms 中选择 PCL 项目?