2011-08-20 5 views
1

나는 현재 진행 콘솔에 소리와 결국 작별 메시지와 함께 종료, 내 하드 드라이브에 비동기 적으로 파일을 다운로드합니다 다음 코드를 가지고 있는지,하지만, 내가 궁금콘솔 응용 프로그램에서 비동기 작업이 끝날 때까지 기다릴 때 Thread.Sleep (Int32.MaxValue)을 피하는 방법은 무엇입니까?

webClient.DownloadProgressChanged.Add(fun args -> 
     if (currentPercentage < args.ProgressPercentage) then 
     Console.WriteLine(args.ProgressPercentage.ToString() + "%") 

     currentPercentage <- args.ProgressPercentage 
) 

webClient.DownloadFileCompleted.Add(fun args -> 
    Console.WriteLine("Download finished!") 
    Environment.Exit 0 
) 

webClient.DownloadFileAsync(new Uri(url_to_download), file_name) 

Thread.Sleep Int32.MaxValue 

Environment.Exit()을 통해 프로그램을 끝내면서 주 스레드에서 "영원히자는"에 의지하지 않고도이를 달성 할 수있는 더 우아한 방법이있을 수 있습니다. 나는 Environment.Exit()을 사용하는 편견이 없지만 가능하면 그것을 피하고 싶습니다! 이 문제를 피할 수있는 유일한 방법은 새 스레드를 생성 한 다음 죽을 때까지 기다리는 것이지만 성가신 것처럼 보입니다. 이 작업을 수행하는 간단한 방법은 무엇입니까?

+1

이 [C#을] 또는 태그 있어야하는데 [# F] ? – Aaronaught

+0

당신이 옳습니다. C#이어야한다. ( –

+0

동기 동작을 원한다면 왜 동기 버전'DownloadFile'을 사용하지 않는가? –

답변

5

당신은이 같은 ResetEvent를 사용할 수 있습니다

static class WebClientEx { 
    public static void DownloadSemiSync(this WebClient webClient, Uri address, string filename) { 
     var evt = new AutoResetEvent(false); 
     webClient.DownloadFileCompleted += (s, e) => evt.Set(); 
     webClient.DownloadFileAsync(address, filename); 
     evt.WaitOne(); 
    } 
} 

: 아직 업데이트 이벤트를 투구하는 동안, 다운로드가 완료 될 때까지 기다립니다 웹 클라이언트에 대한 확장 방법을 쓸 수 C#에서

webClient.DownloadProgressChanged += (f,a) => ... 
AutoResetEvent resetEvent = new AutoResetEvent(false); 
webClient.DownloadFileCompleted += (f, a) => resetEvent.Set(); 
webClient.DownloadDataAsync(new Uri(url_to_download), file_name); 
resetEvent.WaitOne(); 
Console.WriteLine("Finished"); 
2

mutex과 같은 waithandle 파생 클래스를 사용하면 닫을 준비가되었음을 알릴 수 있습니다. 다운로드 완료 방법에 신호를 보내고 앱이 끝날 때까지 기다리십시오. 신호가되면 앱이 자연스럽게 종료됩니다.

1

이 기능을 사용하면 원하는 진행 상황을 정의한 다음 동기 함수로 사용하여 주 코드를 다음과 같이 줄일 수 있습니다.

static void Main() { 
     var webClient = new WebClient(); 
     webClient.DownloadProgressChanged += (s, args) => {..}; 
     webClient.DownloadSemiSync(new Uri("http://.."), "test.bin"); 
     Console.WriteLine("DownloadFinished"); 
    } 

모든 이벤트를 발생 시키지만 종료 될 때까지 대기합니다.

2

는 경우에는,이 과정이 관찰 등의 측면에서 모델링 할 수있는 반응성 확장 라이브러리 (RX)의 팬 :

public static IObservable<int> DownloadURL(string url,string fname) 
    { 
     return Observable.Defer(() => 
     { 
      var sub = new Subject<int>(); 
      var wc = new WebClient(); 
      wc.DownloadProgressChanged += delegate(object sender, DownloadProgressChangedEventArgs e) 
      { 
       sub.OnNext(e.ProgressPercentage); 
       if (e.ProgressPercentage == 100) 
        sub.OnCompleted(); 
      }; 
      wc.DownloadFileAsync(new Uri(url), fname); 
      return sub; 
     }); 
    } 

    public static void Main(string[] str) 
    { 
     foreach (var i in DownloadURL("http://www.google.com", "g:\\google.html").DistinctUntilChanged().ToEnumerable()) 
      Console.WriteLine(i); 
    } 
관련 문제