2011-08-14 9 views
3

다운로드 할 URL의 .txt 파일을 읽는 C#에서 매우 간단한 대량 다운로드 프로그램을 작성하고 있습니다. GUI를 업데이트하기 위해 전역 스레드와 위임자를 설정하고 "Begin"버튼을 누르면 해당 스레드가 생성되고 시작됩니다. 내가 원하는 것은 "Resume"버튼을 누를 때까지 다운로드를 일시 중지 할 수있는 "일시 중지"버튼이 있습니다. 어떻게해야합니까?다운로드 스레드 일시 중지

관련 코드 : 분명히

private Thread thr; 
private delegate void UpdateProgressCallback(int curFile); 

private void Begin_btn_Click(object sender, EventArgs e) 
{ 
    thr = new Thread(Download); 
    thr.Start(); 
} 

private void Pause_btn_Click(object sender, EventArgs e) 
{ 
    Pause_btn.Visible = false; 
    Resume_btn.Visible = true; 
    //{PAUSE THREAD thr} 
} 

private void Resume_btn_Click(object sender, Eventargs e) 
{ 
    Pause_btn.Visible = true; 
    Resume_btn.Visible = false; 
    //{RESUME THREAD thr} 
} 

public void Download() 
{ 
    //Download code goes here 
} 

것은, 나는 노동자를 사용하고 있지 않다, 나는 정말 정말 이해가 안 (당신이 그것을 작동하도록하는 방법을 나에게 보여줄 수없는 한을하지 않으 노동자). 어떤 도움을 주시면 감사하겠습니다.

+2

저는 C# 전문가는 아니지만,이 방법은 파일을 다운로드하는 방법 **에 따라 달라집니다. 'Download()'의 실제 코드는 무엇입니까? – jtbandes

+4

http 연결을 종료하고 이력서에 다시 연결해야합니다. 그렇지 않으면 TCP가 시간 초과됩니다. – sleeplessnerd

+1

다운로드를 중지하면 다시 시작해야합니다. 중지 한 위치를 추적하고 해당 부분을 다운로드하여 무시하거나 다운로드를 다시 시작해야합니다. –

답변

2

System.Net.WebClient.DownloadFile() 또는 System.Net.WebClient.DownloadFileAsync() 방법을 사용하는 경우 수 없습니다 다운로드를 일시 중지하십시오. 이러한 메서드의 차이점은 후자 메서드가 비동기 다운로드를 시작하므로이 메서드를 사용하는 경우 별도의 스레드를 직접 만들지 않아도된다는 것입니다. 유감스럽게도이 두 가지 방법으로 실행 된 다운로드는 일시 중지하거나 다시 시작할 수 없습니다.

System.Net.HttpWebRequest을 사용해야합니다. 다음과 같이 시도하십시오.

class Downloader 
{ 
    private const int chunkSize = 1024; 
    private bool doDownload = true; 

    private string url; 
    private string filename; 

    private Thread downloadThread; 

    public long FileSize 
    { 
     get; 
     private set; 
    } 
    public long Progress 
    { 
     get; 
     private set; 
    } 

    public Downloader(string Url, string Filename) 
    { 
     this.url = Url; 
     this.filename = Filename; 
    } 

    public void StartDownload() 
    { 
     Progress = 0; 
     FileSize = 0; 
     commenceDownload(); 
    } 

    public void PauseDownload() 
    { 
     doDownload = false; 
     downloadThread.Join(); 
    } 

    public void ResumeDownload() 
    { 
     doDownload = true; 
     commenceDownload(); 
    } 

    private void commenceDownload() 
    { 
     downloadThread = new Thread(downloadWorker); 
     downloadThread.Start(); 
    } 

    public void downloadWorker() 
    { 
     // Creates an HttpWebRequest with the specified URL. 
     HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create(url); 

     FileMode filemode; 
     // For download resume 
     if (Progress == 0) 
     { 
      filemode = FileMode.CreateNew; 
     } 
     else 
     { 
      filemode = FileMode.Append; 
      myHttpWebRequest.AddRange(Progress); 
     } 

     // Set up a filestream to write the file 
     // Sends the HttpWebRequest and waits for the response.   
     using (FileStream fs = new FileStream(filename, filemode)) 
     using (HttpWebResponse myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse()) 
     { 
      // Gets the stream associated with the response. 
      Stream receiveStream = myHttpWebResponse.GetResponseStream(); 

      FileSize = myHttpWebResponse.ContentLength; 

      byte[] read = new byte[chunkSize]; 
      int count; 


      while ((count = receiveStream.Read(read, 0, chunkSize)) > 0 && doDownload) 
      { 
       fs.Write(read, 0, count); 
       count = receiveStream.Read(read, 0, chunkSize); 

       Progress += count; 
      } 
     } 
    } 
} 

MSDN의 HttpWebRequest.GetResponse 페이지에서 일부 코드를 사용했습니다.

대신 일시 중지에 대한 스레드를 중지하고 다시 시작에 새로운 하나를 시작하는 다운로드가 다음과 같은 재개 될 때까지, 당신은 또한 대기하도록 while 루프를 변경할 수 있습니다

  while ((count = receiveStream.Read(read, 0, chunkSize)) > 0) 
      { 
       fs.Write(read, 0, count); 
       count = receiveStream.Read(read, 0, chunkSize); 

       Progress += count; 

       while(!doDownload) 
        System.Threading.Thread.Sleep(100); 
      } 

위쪽 쪽은 당신이 할 수있다이다 같은 스레드를 다시 사용할 수 있어야합니다. 단점은 연결 시간이 초과되어 닫힐 수 있다는 것입니다. 후자의 경우이를 감지하고 다시 연결해야합니다.

donwload가 완료 될 때를위한 이벤트를 추가 할 수도 있습니다.

+1

완전히 필요하지 않는 한'Thread.Abort()'를 사용하도록 다른 사람들에게 조언하지 마십시오. 그 방법은 정말로 피해야합니다. – svick

+0

나는 포스터가 원하는 것을 할 수있는 다른 방법을 모른다. 웹 스트림에서 _n_ 바이트를 가져 오는 관리되는 방법을 (동 기적으로 또는 다른 방법으로) 인식하지 못합니다. 내가 틀렸다면 나를 바로 잡아주세요. – Serge

+1

틀렸어. * 스트림 *에 액세스해야합니다. 그러면 언제든지 바이트를 당기거나 읽기를 중지하거나 일시 중지하는 것이 간단합니다. Thread.Abort()는 거의 항상 나쁜 아이디어입니다. –