私はXamarin/MonoTouchを使ってAndroidアプリを構築しています(JavaではなくC#を使用しています)。アプリケーションがサーバーと通信している間にProgressBarを表示したいと考えています。私は非同期を使ってこれをやろうとしていましたが、スレッドの仕組みをよく理解していないし、過去数時間にわたって同じ問題にぶち当たっていました。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()を見ていましたが、何が問題か分かりません。これは、 'await Task.Run()'に対する非同期呼び出しを使用します。コードの残りの半分は例外をキャッチし、その場合はnullを返します。 'await Task.Yield()'を使うと実際にProgressBarの時間が表示されますが、FetchUserDetailsAsync()は何とか同期的に実行されているかのようにアニメーション化されません。このデータのソースコードをOPに掲載します – Captain