2011-12-11 2 views
4

먼저 프로그래밍에 대한 첫 번째 접근 방식으로 C#을 배우기 시작 했으므로 2 개월 전부터 코딩을 시작한 절대 초보자 인 hobbiest를 알려 주시기 바랍니다. 나랑.이벤트 외부에서 이벤트 인수를 사용하는 방법

그래서 무엇을 하려는지 사용자 정의 다운로드 응용 프로그램을 만드는 것입니다. 다운로드 버튼을 제외한 모든 버튼은 "DownloadProgressChangedEventArgs"에서 "percent1"변수를 선택할 수 없습니다. mainForm 생성자보다 먼저 인스턴스화했지만 변경된 값은 읽지 않습니다. 여기

는 대부분의 질문에 관련 밤은 이후 부분적으로 제거 코드,이다 :

public partial class Main : Form 
{ 
//Variables (not all, just the one im having issues with) 
    private double percentage1; 

//Main form constructor 
    public Main(){...} 

//Download File Async custom method 
    public void DldFile(string url, string fileName, string localPath, AsyncCompletedEventHandler completedName, DownloadProgressChangedEventHandler progressName) 
    { 
      WebClient webClient = new WebClient(); 
      webClient.DownloadFileAsync(new Uri(url), localPath + "\\" + fileName); 
      webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(completedName); 
      webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(progressName); 
    } 

//Button 1 click event to start download 
    private void btnDld1_Click(object sender, EventArgs e) 
    { 
     if (url1 != "" && Directory.Exists(localPath1)) 
     { 
      _startDate1 = DateTime.Now; 
      DldFile(url1, fileName1, localPath1, completed1, progress1); 
     } 
     //took out the try/catch, other ifs to try and cut it down 
    } 

//Download Progress Changed event for Download 1 
    public void progress1(object sender, DownloadProgressChangedEventArgs e) 
    { 
     percentage1 = e.ProgressPercentage; //THIS IS WHERE I WAS EXPECTING TO UPDATE "percentage1" 
     progressBar1.Value = int.Parse(Math.Truncate(percentage1).ToString()); 
    } 

//Button that starts all downloads click event where all my problems are at the moment 
    private void btnDldAll_Click(object sender, EventArgs e) 
    { 
     //The progress bar that should let me know the global status for all webClients 
     progressBarAll.Value = (
      int.Parse(Math.Truncate(percentage1).ToString()) + //HERE IS MY PROBLEM 
      int.Parse(Math.Truncate(percentage2).ToString()) + //HERE IS MY PROBLEM 
      int.Parse(Math.Truncate(percentage3).ToString()) + //HERE IS MY PROBLEM 
      int.Parse(Math.Truncate(percentage4).ToString()) + //HERE IS MY PROBLEM 
      int.Parse(Math.Truncate(percentage5).ToString()))/5; //HERE IS MY PROBLEM 

     //Checks if the link exists and starts it from the download button click event 
     if (url1 != "") 
     { 
      btnDld1.PerformClick(); 
     } 
     //Continues for url2, 3, 4, 5 and else 
    } 
} 

그래서 내가 당신을시키는의 발견 가장 짧은 방법입니다 메신저 누락 된 뭔가가 있다면, 해 내려고 알고 알려 주시기 바랍니다, 최대한 빨리 모든 정보를 추가하려고합니다.

"progress1"을 인스턴스화하여 percentage1 변수에 액세스하려고 시도했지만 작동하지 않았습니다. 나는 webClient와 똑같은 일을 시도했지만 시도도하지 않았다. 나는 구글과 stackflow 검색을 아무 소용이 사용했습니다. 그래서 질문이 너무 멍청하거나, 내 사고 방식에서 완전히 그 문제를 보는 다른 방법이 있는지 확실하지 않습니다.

그래서 주된 문제는 "percentage1"변수를 업데이트하고 사용하는 것입니다. "progressBarAll.Value"계산과 관련하여 다른 문제가 있습니다. 올바른 값으로 손을 잡을 수있을 때 해결됩니다. 그렇게 보더라도 걱정할 필요가 없습니다.

긴 게시물에 대한 미안하지만, 문제가 어디에 있는지 잘 모르겠다. 그래서 나는 다른 곳에서 엉망이되지 않도록 더 많은 정보를 제공해야했다.

해피 코딩 D

+0

글쎄 그건 좋은 질문인데, 나는이 글이 하나의 문제에 대해서만 지시되도록 추가하고 싶지 않았다. 그러나 아이디어는'progressBarAll'이 실행중인 다운로드에 따라 업데이트 된 상태를 유지하는 것이 었습니다. dld1이 진행 중이면 download1 진행률을 표시하고, 1을 초과하면 작업중인 모든 다운로드의 평균을 표시합니다. 그러나 나는 이벤트 처리기 외부의 e.Pcentcentage 값에 hanlde를 얻으면이를 해제 할 수 있다고 생각합니다. –

+0

정확히 작동하지 않는 경우, DownloadProgressChanged 이벤트가 실행되지 않았거나 변수가 할당되지 않았습니까? 'progress1()'에 중단 점을 두어 충돌이 발생했는지 확인하십시오. 그런 다음 실제 문제를 추적하기 위해 단계별로 디버깅하십시오. 내가 말할 수있는 범위 내에서 여기서 아무런 잘못을하지 않을 것이므로 문제없이 이벤트 처리기에서 percentage1을 설정할 수 있어야합니다. – aevitas

+0

@Aevitas - 당신이 말한 것처럼 브레이크 포인트를 설정하고, 내가봤을 때 더욱 혼란스러워, 뭔가 이상한 일이 일어나고 있습니다. 다운로드를 클릭하면 모든 이벤트 핸들러가 시작됩니다. 그러나'percentage1 = e.ProgressPercentage'라고'progress1()'에 명시되어 있어도 변수'percentage1'는 'e.ProgressPercentage' 이벤트 인수와 다른 값을 갖습니다. 그리고 progressBarAll은 전혀 움직이지 않습니다. 비록 'percentage *'의 값이 모두 변하는 것을 볼 수 있습니다. –

답변

2

'이벤트 외부의 이벤트 인수 사용'에 대해 생각하지 마십시오. 양식의 상태를 업데이트하는 방법에 대해 생각해보십시오. 나는 더욱 코드를 리팩토링 것

public partial class Main : Form 
{ 
    private double percentage1; 
    private double percentage2; 
    private double percentage3; 
    private double percentage4; 
    private double percentage5; 

    private double Percentage1 
    { 
    get 
    { 
     return this.percentage1; 
    } 
    set 
    { 
     this.percentage1 = value; 
     this.UpdatePercentageAll(); // this will update overall progress whenever the first one changes 

     progressBar1.Value = GetValueFromPercentage(value); 
    } 
    } 
    private double Percentage2 
    // same code as for Percentage1 

    void UpdatePercentageAll() 
    { 
    this.PercentageAll = (this.Percentage1 + this.Percentage2 + this.Percentage3 + this.Percentage4 + this.Percentage5)/5; 
    } 

    static int GetValueFromPercentage(double percentage) 
    { 
    return (int)Math.Truncate(percentage); 
    } 

    double percentageAll; 
    private double PercentageAll 
    { 
    get 
    { 
     return this.percentageAll; 
    } 
    set 
    { 
     this.percentageAll = value; 

     progressBarAll.Value = GetValueFromPercentage(value); 
    } 
    } 

    //Download File Async custom method 
    public void DldFile(string url, string fileName, string localPath, AsyncCompletedEventHandler completedName, DownloadProgressChangedEventHandler progressName) 
    { 
    WebClient webClient = new WebClient(); 
    webClient.DownloadFileAsync(new Uri(url), localPath + "\\" + fileName); 
    webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(completedName); 
    webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(progressName); 
    } 

    //Button 1 click event to start download 
    private void btnDld1_Click(object sender, EventArgs e) 
    { 
    if (url1 != "" && Directory.Exists(localPath1)) 
    { 
     this.StartDownloadFile1(); 
    } 
    //took out the try/catch, other ifs to try and cut it down 
    } 
    void StartDownloadFile1() 
    { 
     this.Percentage1 = 0; 
     _startDate1 = DateTime.Now; 
     DldFile(url1, fileName1, localPath1, completed1, progress1); 
    } 
    //Download Progress Changed event for Download 1 
    public void progress1(object sender, DownloadProgressChangedEventArgs e) 
    { 
    this.Percentage1 = e.ProgressPercentage; // update property, not field 

    //this will be done in property setters 
    //progressBar1.Value = int.Parse(Math.Truncate(percentage1).ToString()); 
    } 
    // then add similar code for other download buttons 

    //Button that starts all downloads click event where all my problems are at the moment 
    private void btnDldAll_Click(object sender, EventArgs e) 
    { 
    //Checks if the link exists and starts it from the download button click event 
    if (url1 != "") 
    { 
     this.StartDownloadFile1(); 
    } 
    //Continues for url2, 3, 4, 5 and else 
    } 
} 

,하지만 난 그것을 코드가 원본에 가까운 경우에 당신이 이해하기 쉽게 될 것이라고 생각 :

를 사용하여 속성을 업데이트 논리를 단순화합니다.

주요 아이디어는 수학적 기능처럼 작동하는 일련의 연결된 속성을 만드는 것입니다. PercentageX 속성을 작성할 때 'PercentageAll을 모든 백분율의 평균으로합시다.'라고 말하는 것이 좋습니다. 그런 다음 각 다운로드가 자체 진행 상태로 업데이트됩니다. 진행률이 업데이트되면 평균값이 업데이트되고 이고 진행 변경 이벤트 핸들러 내에을 기억할 필요가 없습니다.

마지막으로 백분율 속성에서 진행률 막대를 업데이트하고 있습니다. 아주 간단합니다. 비율이 변경되면 바를 업데이트해야합니다. 그렇다면, 왜 사방이 Percentage1을 변경하면 내가 막대를 업데이트 할 필요가 있음을 기억해야합니다이 경우

this.Percentage1 = x; 
this.progressBar1.Value = (int)Math.Truncate(x); 

같은 것을 쓰고 귀찮게. 그리고 나의 예에서는 단지 한 곳에서만 사용되고 매번 작동하는 엄격한 규칙을 만듭니다. 그래서 나는 그것을 잊을 수 없다. 규칙을 변경해야하는 경우 한 곳만 변경해야하므로 다시 실수를 할 수 없습니다.

내가 보여주는 기술은 잘 알려진 규칙으로 표현할 수 있습니다. '하나의 규칙 - 한 곳'. 프로그램에 존재하는 각 논리 규칙을 나타내는 코드에서 한 곳만 사용해야합니다. 그것은 매우 중요한 아이디어입니다, 당신이 배우고 그것을 사용하는 것이 좋습니다.

+0

Pavel 내가 게시 한 코드의 메커니즘을 이해하지 못했습니다. 나는 너의 포스트에 관하여 어떤 특정한 질문도, 다만 그것을 모두 즉시 얻는 경험이 없다. 그래서 이것을 인쇄하고, 모든 것을 이해하고, 시험하고, 다시 답장 할 것입니다. 하지만 인스턴트 메신저 거의 긍정적 인 대답, 빠른 답변을 주셔서 감사합니다, D –

+0

난 그냥 코드를 통해 가서'GetValueFromPercentage (값)'메서드를 입력하는 것을 잊었 생각. 다른 한편으로는 확실하지 않지만 다운로드마다 하나의 진행률 표시 줄 + 진행률 표시 줄이 있으므로 개별 진행률 표시 줄은 자신의 다운로드에 따라 이동하고 progressBarAll은 다운로드가 진행되는 총 비율에 따라 이동합니다. 귀하의 코드를 읽고 난 당신이 어떤 일이 일어 났는지 알려주기 위해 1progressBar를 사용하려한다고 생각합니다. 내가 너를 이해했는지 알려주지. –

+0

@FernandoSilva 죄송합니다. 좀 더 완전한 코드를 작성해야합니다. 방금 GetValueFromPercentage 메소드를 놓쳤습니다. 그리고 당신 말이 맞습니다. 모든 다운로드에 대해 하나의 진행 막대가 있다는 것을 이해했습니다. 코드와 대답을 모두 업데이트했습니다. 그것을 확인하시기 바랍니다. –

관련 문제