0

我仍在努力学习 Xamarin.iOs,并且对于概念上的一点证明,我正在使用 Monotouch.Dialog 创建一个员工目录。它在 iPhone 模拟器上运行良好,但是当我在物理设备上执行它时,会发生 3 件奇怪的事情:

  1. 随机(有时在模拟器上,但更常见于设备上),我在异步方法中调用 HttpWebRequest.GetRequestStream() 时出现超时异常。但是,每次调用该方法时,我都会创建一个新的 HttpWebRequest,并且我认为我正确地关闭并处理了所有内容。这是代码片段:

    var wr = HttpWebRequest.Create(url);
    byte[] streamContent = System.Text.Encoding.UTF8.GetBytes(body);
    Stream dataStream = wr.GetRequestStream(); //timeout on that statement !
    dataStream.Write(streamContent, 0, streamContent.Length);
    dataStream.Close();
    using (var response = (await wr.GetResponseAsync().ConfigureAwait(false)))
    {
        if (response != null)
        {
            try
            {
                var webResponse = response as HttpWebResponse;
                if (webResponse != null && webResponse.StatusCode == HttpStatusCode.OK)
                {
                    using (StreamReader reader = new StreamReader(webResponse.GetResponseStream()))
                    {
                        var responseText = reader.ReadToEnd();
                        result = JsonConvert.DeserializeObject<T>(responseText);
                        reader.Close();
                    }
                }
            }
            finally
            {
                if (response != null)
                {
                    response.Close();
                }
            }
        }
    }
    
  2. 我异步加载数据,但如果我使用 async / await 关键字,我的应用程序无法在设备上启动,因为看起来 UI 线程正在等待我的加载完成,这需要太多时间。我改用 Task.Factory.StartNew 解决了这个问题,但我想知道为什么设备和模拟器上的行为不同。

  3. 我的最后一个问题是,当我从我的网络服务收到答案时,我构建了一个添加到我的部分的元素列表。我有很多元素,但没有那么多(大约 700 个)。在模拟器中刷新屏幕大约需要 2 秒,但在设备上需要 1 多分钟(第四代 ipod touch)。这是我用来创建元素和刷新屏幕的代码(它运行异步,所以我使用 InvokeOnMainThread()):

    private void updateEmployeeList(IEnumerable<EmployeSummary> list, Section section)
    {
        if (list != null && list.Any())
        {
            var q = list.Select(item =>
            {
                StyledStringElement newCell = new StyledStringElement(item.FullName) { Accessory = UITableViewCellAccessory.DisclosureIndicator };
                newCell.Tapped +=
                () => _detailScreenVM.ShowDetail(item);
                return newCell;
            }).ToList();
            _logger.Log("Items to add : {0}", q.Count);
            InvokeOnMainThread(() =>
            {
                _logger.Log("Starting updating screen");
                section.AddAll(q);
                _logger.Log("Ending updating screen.");
            });
        }
    }
    

这是执行时控制台的结果:

  • 要添加的项目:690 at 15:29:57.896041
  • 在 15:29:57.903079 开始更新屏幕
  • 在 15:31:03.548430 结束更新屏幕

这可能是我对异步编程模型做错了,但我无法弄清楚到底是什么。

谢谢

4

1 回答 1

1
  1. 我猜超时是System.Net.WebException: The operation has timed out at System.Net.HttpWebRequest.GetRequestStream(). 如果你查看Response.StatusCode异常的属性,你肯定会发现它是一个4xxhttp错误。这意味着服务器而不是客户端对此负责。所以修复这个服务器端。
  2. AppDelegate.FinishedLaunching返回的时间很短(17 秒)。如果您超过此时间,您的应用程序将被终止。启动后台线程是要走的路。模拟器上的限制可能略有不同,因为众所周知,模拟器中的调试代码比在设备上运行发布代码要慢。
  3. 我不知道这里出了什么问题,也不知道 的内部结构MonoTouch.Dialog,但解决它的一种方法是使用 a UITableView,因此单元格的渲染仅在需要时发生。
于 2013-09-30T07:57:48.067 回答