2013-10-20 1 views
0

웹에서 두 개의 JSON 파일을 다운로드하고 난 후 두 페이지를로드 할 수 있지만 이전에는 허용하지 않습니다. 그러나 페이지를로드하기 위해 설정해야하는 ManualResetEvent은 절대로 "실행되지 않습니다." 비록 내가 그것이 도착한다는 것을 알지만, WaitOne 결코 반환하지 않는다. Downloads (다운로드) 시작ManualResetEvent wait는 설정 한 후에 해제되지 않습니다.

방법 :

private void Application_Launching(object sender, LaunchingEventArgs e) 
{ 
    PhoneApplicationService.Current.State["doneList"] = new List<int>(); 
    PhoneApplicationService.Current.State["manualResetEvent"] = new ManualResetEvent(false); 

    Helpers.DownloadAndStoreJsonObject<ArticleList>("http://arkad.tlth.se/api/get_posts/", "articleList"); 
    Helpers.DownloadAndStoreJsonObject<CompanyList>("http://arkad.tlth.se/api/get_posts/?postType=webbkatalog", "catalog"); 
} 

다운로드 방법, 즉 (이 경우 생성자)

public SenastePage() 
{ 
    InitializeComponent(); 

    if ((PhoneApplicationService.Current.State["doneList"] as List<int>).Count < 2) 
    { 
     (PhoneApplicationService.Current.State["manualResetEvent"] as ManualResetEvent).WaitOne(); 
    } 
    SenasteArticleList.ItemsSource = (PhoneApplicationService.Current.State["articleList"] as ArticleList).posts; 
} 

내가 만약 ManualResetEvent

public static void DownloadAndStoreJsonObject<T>(string url, string objName) 
{ 
    var webClient = new WebClient(); 
    webClient.DownloadStringCompleted += (sender, e) => 
    { 
     if (!string.IsNullOrEmpty(e.Result)) 
     { 
      var obj = ProcessJson<T>(e.Result); 
      PhoneApplicationService.Current.State[objName] = obj; 


      var doneList = PhoneApplicationService.Current.State["doneList"] as List<int>; 
      doneList.Add(0); 

      if (doneList.Count == 2) // Two items loaded 
      { 
       (PhoneApplicationService.Current.State["manualResetEvent"] as ManualResetEvent).Set(); // Signal that it's done 
      } 
     } 
    }; 

    webClient.DownloadStringAsync(new Uri(url)); 
} 

필요한 대기 방법을 설정합니다 해당 생성자에 액세스하기 전에 기다리십시오. if 문을 쉽게 전달합니다. WaitOne에 잡히지는 않겠지 만, 즉시 호출하면 나는 막히고 반환하지 않습니다 ...

아이디어가 있으십니까?

+2

교착 상태입니다. WebClient의'DownloadStringCompleted' 이벤트는'WaitOne'으로 블로킹하는 스레드와 동일한 UI 스레드에서 실행됩니다. 어쨌든 UI 스레드를 막론하고 차단하지 않아야합니다. 데이터를 기다리는 동안로드 애니메이션을 표시하는 것이 좋습니다. –

+0

디버거가이 정지 상태에있는 동안 디버거에 놓을 수 있으며 doneList.Count 및 manualResetEvent 변수를 검사하여 해당 시점에 설정된 값을 확인할 수 있습니까? –

+0

@KooKiz : 스플래시 화면을 표시하지 않거나, 어떤 시점에서 두 다운로드가 모두 완료된 것을 알고 있어야합니다. ManualResetEvent가 필요하지 않습니까? – SamiHuutoniemi

답변

1

UI 스레드 차단은 반드시 피해야합니다. 특히 데이터를 다운로드 할 때 : 응용 프로그램이 매우 불안정한 네트워크를 가진 전화에서 실행되고 있다는 것을 잊지 마십시오. 데이터로드에 2 분이 소요되면 UI가 2 분 동결됩니다. 그것은 끔찍한 사용자 경험이 될 것입니다.

여러 가지 방법으로이를 방지 할 수 있습니다. 예를 들어, 같은 논리를 유지할 수 있지만, 대신 UI 스레드의 배경 스레드에서 대기 : 당신이 원하는 결과에 도달 할 수있는 신속하고 더러운 방법

public SenastePage() 
{ 
    // Write the XAML of your page to display the loading animation per default 
    InitializeComponent(); 

    Task.Factory.StartNew(LoadData); 
} 

private void LoadData() 
{ 
    ((ManualResetEvent)PhoneApplicationService.Current.State["manualResetEvent"]).WaitOne(); 

    Dispatcher.BeginInvoke(() => 
    { 
     SenasteArticleList.ItemsSource = ((ArticleList)PhoneApplicationService.Current.State["articleList"]).posts; 

     // Hide the loading animation 
    } 
} 

합니다. 또한 작업을 사용하여 코드를 다시 작성하고 모두 완료되면 Task.WhenAll을 사용하여 작업을 트리거 할 수 있습니다.

0

아마도 논리 문제가 있습니다. SenastePage() 생성자에서 doneList 수가 2보다 작은 경우에만 set 이벤트를 기다리고 있습니다. 그러나 doneList 수가 2와 같을 때까지 설정된 이벤트를 발생시키지 않습니다. 화재가 발생하기 전에 설정된 이벤트를 듣고 있습니다.

+0

그 점이 아닌가요? 개수가 2 이상이면 다운로드가 완료되고 기다릴 필요가 없습니다. 2보다 작 으면 기다리기 시작합니다. – SamiHuutoniemi