首页 > 解决方案 > 在 Xamarin Forms 中挂起的 PostAsync 在模拟器上工作,但在实际手机上挂起

问题描述

我有 Xamarin Forms 项目,我正在尝试向/从 Web API 发布和获取数据,但是当我进行异步/等待调用时,它可以在模拟器上运行(并非没有原始问题!)但是当我尝试它在我的实际手机(三星 S8+)上,它只是无限期挂起。

请注意,我现在只专注于 Android 部分,而不是 iOS,并不是说问题应该对两者都有任何影响。

这是我正在使用的代码:

IDataService.cs

Task<TResponse> PostDataAsync<TRequest, TResponse>(string uri, TRequest data)
    where TRequest : class
    where TResponse : class;

数据服务.cs:

public async Task<TResponse> PostDataAsync<TRequest, TResponse>(string 
             additionalUri, TRequest data)
    where TRequest : class
    where TResponse : class
    {
        return await WebClient
        .PostData<TRequest, TResponse>
        (string.Concat(this.Uri, additionalUri), data);
    }

Web客户端.cs

using (var client = new HttpClient())
{
    var jsonData = JsonConvert.SerializeObject(data);
    using (var response = await client.PostAsync(
        uri, 
        new StringContent(jsonData, 
            Encoding.UTF8, 
            "application/json" )))
    {
        if (response.IsSuccessStatusCode)
        {
            var content = await response.Content.ReadAsStringAsync();
            return JsonConvert.DeserializeObject<TResponse>(content);
        }
    }
}

方法一:

LoginPageViewModel.cs

public DelegateCommand SignInCommand => _signInCommand ??
       (this._signInCommand = new DelegateCommand(SignInCommandAction));


private async void SignInCommandAction()
{
    try
    {
        ....
        var user = await this._dataService
        .PostDataAsync<LoginRequestDto,
         LoginResponseDto>(@"Accounts/Login", loginRequestDto);     
         ....
    }
    ...
}

方法2:

LoginPageViewModel.cs

public DelegateCommand SignInCommand => _signInCommand ?? 
           (this._signInCommand = 
            new DelegateCommand(async () => await SignInCommandAction()));


private async Task SignInCommandAction()
{
    try
    {
        ....
        var user = await this._dataService
        .PostDataAsync<LoginRequestDto,
         LoginResponseDto>(@"Accounts/Login", loginRequestDto);     
         ....
    }
    ...
}

当我调用本地 Web API 即http://10.0.2.2/MyApp/api/时,PostDataAsync 可以使用这两种方法,但是当从 Web 提供程序(即http://myapp-123-site)调用外部我的 Web 服务时,这两种方法仍然挂起.atempurl.com/api/这是一个用于测试目的的临时 url。

这同样适用于我的 GetDataAsync,它没有被证明,但我只是想我会提到它。

基于上述,您会认为我的 async/await 代码是正确的,因为它在调用本地 web api 时有效,但是在调用远程 web api 时导致它挂起。

如前所述,我确实在清单中启用了我的 INTERNET 权限。

在此处输入图像描述

欢迎提出任何建议?

谢谢。

更新-1:

请注意,我刚刚尝试在同一函数中调用 GET 操作,这在模拟器中工作,但与实际的手机挂起。

using (var client = new HttpClient())
{
    using (var response = await client.GetAsync(uri))
    {
        if (response.IsSuccessStatusCode)
        {
            var content = await response.Content.ReadAsStringAsync();
            return Newtonsoft.Json.JsonConvert
                   .DeserializeObject<TResponse>(content);
        }
   }
}

更新2:

这在某种程度上有效,我不知道为什么!唯一想到的是我升级了我的库。这包括棱镜,它可能是问题的根源,但我不知道。

抱歉,我无法提供更多细节。我可以恢复我的代码并尝试查看它是否再次挂起,但考虑到我已经花在这方面的时间,我只是没有时间去尝试更多。对不起。

标签: xamarinasynchronousxamarin.formsasync-await

解决方案


请求的 url 是IP域名

  • 如果是ip,则多个网段的设备只能访问公网的IP。
  • 如果是域名,需要支持域名解析服务。

如果暂时没有这些环境,需要设备IP和服务器IP在同一网段。

当我调用本地 Web API 即http://10.0.2.2/MyApp/api/时,PostDataAsync 可以使用这两种方法,但是当从 Web 提供程序(即http://myapp-123-site)调用外部我的 Web 服务时,这两种方法仍然挂起.atempurl.com/api/这是一个用于测试目的的临时 url。

从这个现象来看,应该是临时url的原因。从 这个 域名 ( myapp-123-site.atempurl.com) 中 找不到 正确 的 本地 IP ( 10.0.2.2) . 当 你 在 本地 网络 测试 时 , 我 猜 这 会 工作 . 但是 实际 手机 的 网络 可能 和 本地 网络 不 一样 , 比如 使用 3G / 4G网络,那就不行了。


推荐阅读