2012-03-15 3 views
1

xml 파일에서 생성 된 컬렉션을 반환하는 함수를 개발 중입니다.WebClient - 파일이 다운로드 될 때까지 대기

처음에는 테스트를 위해 로컬 xml 파일을 사용했지만 이제는 서버에서 실제 xml 파일을 다운로드 할 준비가되었습니다. WebClient 객체에 OpenReadCompleted 이벤트 핸들러가 필요하다는 사실 때문에이 작업을 수행 할 수있는 방법을 알기 위해 고심하고 있습니다.이 핸들러에서 콜렉션 데이터를 반환 할 수 없으며이 핸들러가 실행될 때까지 원래 함수가 종료되었습니다. .

public static ObservableCollection<OutletViewModel> GetNear(GeoCoordinate location) 
{ 
    ObservableCollection<OutletViewModel> Items = new ObservableCollection<OutletViewModel>(); 

    // Load a local XML doc to simulate server response for location 
    XDocument xDoc = XDocument.Load("SampleRemoteServer/outlet_list.xml"); 

    foreach (XElement outlet in xDoc.Descendants("outlet")) 
    { 
     Items.Add(new OutletViewModel() 
     { 
      Name = outlet.Attribute("name").Value, 
      Cuisine = outlet.Attribute("cuisine").Value 
     }); 
    } 

    return Items; 
} 

가 어떻게 이벤트 핸들러 실행이이 기능에 파일을로드 할 수 있습니다, 다음 기능을 계속 다음과 같이

내 원래 코드는?

내가 생각할 수있는 것은 이벤트 처리기 코드에 의해 업데이트되는 변수를 계속 확인하기 위해 루프를 추가하는 것 뿐이라고 생각할 수 있습니다. 좋은 해결책이 아닌 것 같습니다.

덕분에, 조쉬

+0

당신은 당신은 내가 비동기보고 시작했습니다 –

+0

설계를 조정할 필요가 있다는 것을 의미하더라도, 그것은 비동기 요청에 독서 가치가있을 수 있으므로, UI 스레드를 차단하지 않으/키워드를 기다려주세요, 감사합니다! – Josh

답변

1

비동기 프로그래밍을 살펴보아야합니다. 하나 (구식) 방법은 공개 이벤트를 구현하고 호출 클래스에서 해당 이벤트를 구독하는 것입니다.

그러나 콜백을 사용하면 더 우아합니다.

public static void Main(string[] args) 
{ 
    List<string> list = new List<string>(); 

    GetData(data => 
    { 
    foreach (var item in data) 
    { 
     list.Add(item); 
     Console.WriteLine(item); 
    } 
    Console.WriteLine("Done"); 
    }); 
    Console.ReadLine(); 
} 

public static void GetData(Action<IEnumerable<string>> callback) 
{ 
    WebClient webClient = new WebClient(); 
    webClient.DownloadStringCompleted += (s, e) => 
    { 
     List<string> data = new List<string>(); 
     for (int i = 0; i < 5; i++) 
     { 
     data.Add(e.Result); 
     } 
     callback(e.Error == null ? data : Enumerable.Empty<string>()); 
    }; 

    webClient.DownloadStringAsync(new Uri("http://www.google.com")); 
} 

당신이 C# async 악 대차 (link for WP7 implementation)로 이동하려면

, 당신은 새로운 asyncawait를 사용하여 구현할 수 있습니다 : 나는 (쓸모없는,하지만 여전히 개념적으로 유효) 당신이에 구축 할 수 있다는 예를 단순한를 채찍질 키워드 :

public static async void DoSomeThing() 
{ 
    List<string> list = new List<string>(); 
    list = await GetDataAsync(); 

    foreach (var item in list) 
    { 
    Console.WriteLine(item); 
    } 
} 

public static async Task<List<string>> GetDataAsync() 
{ 
    WebClient webClient = new WebClient(); 
    string result = await webClient.DownloadStringTaskAsync(new Uri("http://www.google.com")); 

    List<string> data = new List<string>(); 
    for (int i = 0; i < 5; i++) 
    { 
    data.Add(result); 
    } 
    return data; 
} 
+0

물론, .Net 4.5는 Window-Phone-7에 대한 옵션이 아닙니다 ... –

+0

유용하게 보입니다. 이것을 WP7에서 사용할 수 있도록해야합니다. 내일 제대로 볼 것입니다. .. http://www.abhisheksur.com/2011/04/async-support-for-silverlight-and-wp7.html – Josh

+0

WP7 앱과 함께 비동기 CTP를 사용할 수 있습니다. http://msdn.microsoft.com/en -us/vstudio/gg316360 –

2

당신은 완성 된 이벤트에 foreach() 루프를 이동합니다.

그리고 실제로 원래의 방법으로는 어떤 것도 반환 할 수 없습니다. void으로 지정하십시오.

비동기 I/O가 작동하는 방식으로 익숙해집니다. 디자인을 재고해야합니다.

관련 문제