我正在通過Xamarin/MonoTouch(所以使用C#而不是Java)構建一個Android應用程序,並希望在應用程序與服務器通信時顯示ProgressBar。我一直在嘗試使用async來做到這一點,但我對線程的工作方式並沒有很好的理解,而且我在過去幾個小時裏遇到了同樣的問題 - ProgressBar在我的方法調用之後顯示,而不是之前。我的代碼在OnCreate()方法中,我也將其重寫爲異步。這是它:用Xamarin顯示Android ProgressBar
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;
}
}
非常有趣。當我嘗試Task.Delay()時,事情就像我想的那樣工作。我正在調查FetchUserDetailsAsync以查看可能存在的問題 – Captain
我花了一些時間查看FetchUserDetailsAsync(),我無法真正瞭解可能是什麼問題。它使用異步調用來'等待Task.Run()'。代碼的另一半隻是捕獲異常,如果情況如此,則返回null。使用'await Task.Yield()'實際上給ProgressBar時間顯示,但它不動畫 - 就像FetchUserDetailsAsync()在某種程度上仍然同步運行一樣。我將在OP中發佈這些數據的源代碼 – Captain