2017-05-18 1 views
1

코드 중간에서 볼 수 있듯이 파일을 다운로드 할 때까지 기다리는 추편 스레드 차단 코드가 있으며 명령 줄에서 진행률 보고서를 사용할 수도 있습니다. 내 말은, 아직도 Thread.Sleep()보다 낫다거나 바쁘게 기다리는 것입니까? 어쨌든, 나는 Wait/Pulse에 대해 알고 있지만 어떻게 적용 할 지 모르겠습니다.진행 보고서와 함께 DownloadFileAsync()를 기다리는 동안 주 스레드 일시 중지

단일 비동기 작업을 가장 깨끗하게 처리하기 위해 내 리팩터링을 완전히 완료 했습니까? 하나는 WebClient 클래스에서 무언가를 재정의하여 Wait/Pulse 대기 유형을 사용할 수 있습니까?

프로젝트 및 해당 기능 : Github

관련 조각 :이 내가 C#으로 작성한 나의 첫 번째 프로젝트는

static void GetPatch(KeyValuePair<string, string> entry, string part) 
{ 
    string url = entry.Key, 
     fname = url.Substring(url.LastIndexOf("/", StringComparison.Ordinal) + 1), 
     path = G.patchPath + "\\" + fname; 
     bool exists = File.Exists(path); 
    Console.Write(fname + " ... "); 
    string message = "local"; 
    if ((exists && GetSHA1(path) != entry.Value) || !exists) 
    { 
     if (exists) File.Delete(path); 
     G.wc.DownloadProgressChanged += Wc_DownloadProgressChanged; 
     G.wc.DownloadFileAsync(new Uri(url), part); 
     while (G.wc.IsBusy) 
     { 
      // There must be a better way 
      new System.Threading.ManualResetEvent(false).WaitOne(200); 
     } 
     G.wc.DownloadProgressChanged -= Wc_DownloadProgressChanged; 
     message = "done"; 
    } 
    if (File.Exists(part)) File.Move(part, path); 
    G.patchFNames.Enqueue(fname); 
    Green(message); 
} 

private static void Wc_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e) 
{ 
    int p = e.ProgressPercentage; 
    p = p < 100 ? p : 99; 
    Console.Write("{0:00}%\b\b\b", p); 
} 

나와 함께하시기 바랍니다 곰과 내가 절대 해요 OOP 및 C# 초보.

public void DownloadFile(Uri uri, string desintaion) 
{ 
    using(var wc = new WebClient()) 
    { 
    wc.DownloadProgressChanged += HandleDownloadProgress; 
    wc.DownloadFileCOmpleted += HandleDownloadComplete; 

    var syncObj = new Object(); 
    lock(syncObject) 
    { 
     wc.DownloadFileAsync(sourceUri, destination, syncObject); 
     //This would block the thread until download completes 
     Monitor.Wait(syncObject); 
    } 
    } 

    //Do more stuff after download was complete 
} 

public void HandleDownloadComplete(object sender, AsyncCompletedEventArgs args) 
{ 
    lock(e.UserState) 
    { 
     //releases blocked thread 
     Monitor.Pulse(e.UserState); 
    } 
} 


public void HandleDownloadProgress(object sender, DownloadProgressChangedEventArgs args) 
{ 
    //Process progress updates here 
} 
+0

코드와 명확성을 분명히 조사해야하지만 일반적으로 나는 올바른 방향으로 가고 있다고 생각합니다. 2 개의 비동기 프로세스가 필요합니다. 하나는 파일 다운로드 용이고 다른 하나는 진행 상태 모니터링 용입니다. 두 번째 프로세스는 비동기 적이어야하므로 UI를 차단하지 않으며 디스패처를 사용하여 UI를 업데이트해야합니다. – Andrei

+0

찾고 계신가요? https://alexfeinberg.wordpress.com/2014/09/14/how-to-use-net-webclient-synchronously-and-still-receive-progress-updates/ – MistyK

+0

async \ await으로 이동하는 것은 어떨까요? 기다릴 수있는'DownloadFileTaskAsync'가 있습니다. 그러면이 코드에서 대부분의 추함을 버릴 것입니다. – Evk

답변

2

내 의견에 URL에서 코드를 복사하자 업데이트 진행률 표시 줄. UI 프로세스가 아니라면 직접 할 수는 없지만 UI 업데이트를 "파견"해야합니다.

+0

예, 완벽합니다. userToken 오버로드가 핵심이라는 것을 알고 있었지만 슬프게도 MSDN은 그다지 잘 설명하지 못하고 예제가 부족합니다. – user1263513

0

귀하의 높은 수준의 코드가 모든 N 밀리이

public async Task StartFileDownload() 
{ 
    var downloadTask = StartDownload(); 
    var monitoringTask = StartMonitoringProgress(); 

    await Task.WhenAll(downloadTask, monitoringTask); 
} 

모니터링 작업이 확인되어야한다 다운로드 진행 상황과 같아야합니다

+1

사실상, 그가 [Event-based Asynchronous Pattern (EAP)] (https : // msdn)을 사용하는'DownloadFileAsync() '를 사용할 때'Task'를 반환하는'DownloadFileTaskAsync()'를 사용하고 있음을 당신의 코드는 암시합니다. microsoft.com/en-us/library/wewwczdw(v=vs.110).aspx). – Cameron

관련 문제