2016-08-16 3 views
1

Xamarin/MonoTouch (Java가 아닌 C#을 사용)를 통해 Android 앱을 제작 중이며 앱이 서버와 통신하는 동안 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 프레임 건너 뛰기!"와 같은 메시지를주었습니다. 응용 프로그램이 주 스레드에서 너무 많은 작업을 수행하고있을 수 있습니다. "

앞서 말했듯이, 나는 실을 꿰기에 익숙하지 않았기 때문에, 나는 순진하게 뭔가 잘못하고있는 것이 가능합니다. 누구든지이 문제에 대한 해결책을 가지고 있습니까?

EDIT :

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; 
     } 
    } 

답변

1

그것은 UI 스레드를 차단 또는 FetchUserDetailsAsync ParseUserDetails 하나 같다 : 여기 FetchUserDetailsAsync 소스 코드이다. Task.Sleep (5000)이 동 기적으로 실행되기 때문입니다. Task.Delay (5000)를 기다려보십시오; 진행률 표시 줄이 나타나는지 FetchUserDetailsAsync 행에 추가하십시오. 그렇다면 FetchUserDetailsAsync 구현으로 이동하여 비동기로 구현해야합니다.

+0

매우 흥미 롭습니다. 내가 Task.Delay()를 시도했을 때, 나는 원하는대로 일했다. 나는 FetchUserDetailsAsync에 무엇이 문제인지를 지금보고있다. – Captain

+0

나는 FetchUserDetailsAsync()를 보면서 시간을 보냈는데 그 문제가 무엇인지 이해할 수 없다. 그것은'await Task.Run()'에 비동기 호출을 사용합니다. 나머지 절반은 예외를 잡아 내고 null 인 경우를 반환합니다. 'await Task.Yield() '를 사용하면 실제로 ProgressBar에 표시 할 시간이 주어 지지만 FetchUserDetailsAsync()가 여전히 동 기적으로 실행중인 것처럼 움직이지는 않습니다. 나는이 데이터에 대한 소스 코드를 OP에 올릴 것이다. – Captain

1

문제점을 파악했습니다. 내 FetchUserDetailsAsync 메서드에서 GetResponseAsync() 대신 GetResponse()을 호출했습니다.