【问题标题】:Show Android ProgressBar with Xamarin使用 Xamarin 显示 Android ProgressBar
【发布时间】:2016-08-16 15:32:32
【问题描述】:

我正在通过 Xamarin/MonoTouch(因此使用 C# 而不是 Java)构建一个 Android 应用程序,并希望在应用程序与服务器通信时显示一个 ProgressBar。我一直在尝试使用异步来执行此操作,但我对线程的工作原理并没有很好的理解,而且在过去的几个小时里我一直遇到同样的问题 - ProgressBar 在我的方法调用之后而不是之前显示.我的代码在 OnCreate() 方法中,我也将其重写为异步。这里是:

        loginButton.Click += async (sender, e) =>
        {
            progbar.Visibility = ViewStates.Visible;

            var userFetcher = new UserFetcher();
            var json = await userFetcher.FetchUserDetailsAsync(/*parameters*/);
            //the above method is async and returns a Task<JsonValue>
            ParseUserDetails(json); //another method I created

            progbar.Visibility = ViewStates.Invisible;
            //do some stuff using the parsed data
        };

我遇到的问题是 FetchUserDetailsAsync 似乎阻塞了我的线程。我一直在通过关闭服务器来测试它,这样它需要很长的响应时间(但即使我测试像 Thread.Sleep(5000) 这样的东西我也有同样的问题)。调用该方法后,它会依次运行progbar.Visibility = ViewStates.Visible;progbar.Visibility = ViewStates.Invisible; - 我知道这一点,因为当我注释掉 Invisible 部分时,在我的方法从服务器获得“响应”后会出现 ProgressBar。编译器也一直在给我类似“跳过 67 帧!应用程序可能在其主线程上做太多工作”之类的消息。

就像我之前说的,我对线程并没有真正的经验,所以很可能我只是天真地做错了什么。有没有人可以解决这个问题?

编辑:这是 FetchUserDetailsAsync 的源代码:

    public async Task<JsonValue> FetchUserDetailsAsync(string url, string username, string password)
    {
        HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(new Uri(url));
        request.ContentType = "application/json";
        request.Method = "GET";

        string myBasicHeader = AuthenticationHelper.MakeHeader(username, password);

        request.Headers.Add("Authorization", "Basic " + myBasicHeader);

        try
        {
            using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
            {
                using (Stream stream = response.GetResponseStream())
                {
                    JsonValue jsonDoc = await Task.Run(() => JsonObject.Load(stream));
                    return jsonDoc;
                }
            }
        }
        catch (WebException e)
        {
            Console.WriteLine(e.ToString());
            if (e.Status == WebExceptionStatus.ProtocolError)
            {
                var response = e.Response as HttpWebResponse;
                if (response != null)
                {
                    Console.WriteLine("HTTP Status Code: " + (int)response.StatusCode);
                }
                else
                {
                    Console.WriteLine("No http status code available");
                }
            }
            return null;
        }
    }

【问题讨论】:

    标签: c# android multithreading xamarin mono


    【解决方案1】:

    看起来 FetchUserDetailsAsync 或 ParseUserDetails 阻塞了 UI 线程。因为 Task.Sleep(5000) 是同步运行的。尝试等待 Task.Delay(5000);在 FetchUserDetailsAsync 行中查看进度条是否显示。如果是这样,那么您可能需要进入 FetchUserDetailsAsync 实现以确保它是异步实现的

    【讨论】:

    • 非常有趣。当我尝试 Task.Delay() 时,一切都如我所愿。我现在正在调查 FetchUserDetailsAsync 看看可能是什么问题
    • 我花了一些时间查看 FetchUserDetailsAsync(),但我无法真正理解它的问题所在。它使用对await Task.Run() 的异步调用。如果是这种情况,另一半代码只是捕获异常并返回 null。使用await Task.Yield() 实际上让 ProgressBar 有时间显示,但它没有动画 - 好像 FetchUserDetailsAsync() 不知何故仍在同步运行。我将在 OP 中发布此数据的源代码
    【解决方案2】:

    我发现了这个问题。我在 FetchUserDetailsAsync 方法中调用了 GetResponse() 而不是 GetResponseAsync()

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-11
      • 2016-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多