2010-02-11 5 views
0

아래의 코드에서 Process 개체를 사용하여 일련의 DOS 배치 파일을 실행하고 있습니다. 예를 들어 스크립트 목록을 줄이려고합니다.예외를 throw하는 기본 UI 스레드 코드를 실행할 수 있습니까?

후속 (1+) 스크립트는 for 루프 대신 이벤트 처리기를 통해 실행됩니다. 이렇게하면 각 후속 스크립트는 이전 스크립트가 완료 될 때만 실행됩니다. 이제 두 번째 스크립트를 실행할 때 어떤 이유로 인해 잡힌 예외를 가져 와서 상태 표시 줄에 오류 메시지를 채울 수 없습니다.

app-config 파일에 잘못된 스크립트 이름을 입력했을 때 테스트 중이며 용의자 델리게이트를 잘못 사용하고 있습니다. 내 익명의 대리인은 "새로운 코드"와 기존 클래스 메서드의 조합으로 구성됩니다. 그게 뭐야 내가 생각은 틀렸다; 모두이 방향으로 나를 밀어 수 있다면 왜 나는 그것을 감사하겠습니다)

참고 :

private void copybutton_Click(object sender, EventArgs e) 
    { 

     InitializeBar(); 

     this.nbr_of_copy_exits_ = 0; 
     this.RunCopyScript(this.nbr_of_copy_exits_); 
     return; 
    } 

private void RunCopyScript(Int32 CopyScriptIdx) 
    { 
     Process proc = null; 
     try 
     { 
      proc = this.ObtainProcess(this.client_dest_dir_ + this.copy_scripts_[CopyScriptIdx]); 
      proc.EnableRaisingEvents = true; 
      proc.Exited += new EventHandler(CopyExited); 
      proc.Start(); 
      this.progressBar.Value = ProgressInPercent(this.copy_scripts_.Count(), CopyScriptIdx); 
     } 
     catch (Exception ex) 
     { 
      this.UpdateControl(this.toolStripStatusLabel1, "Error involving " + this.copy_scripts_[CopyScriptIdx] + ": " + ex.Message); 
      this.copybutton.BackColor = Color.Red; 
     } 
     return; 
    } 

void CopyExited(object sender, EventArgs e) 
    { 
     System.Diagnostics.Process senderProcess 
      = sender as System.Diagnostics.Process; 

     this.Invoke((MethodInvoker)delegate 
     { 
      if (++this.nbr_of_copy_exits_ == this.copy_scripts_.Count()) 
      { 
       this.UpdateControl(this.toolStripStatusLabel1, "Copying COMPLETE."); 
       this.progressBar.Value = 0; 
      } 
      else 
      { 
       this.RunCopyScript(this.nbr_of_copy_exits_); 
      } 
     }); 
    } 

     private void UpdateControl(ToolStripStatusLabel tssl, String text) 
    { 
     tssl.Text = text; 
     tssl.Refresh(); 
    } 

답변

1

"nosuchscript.bat, goodname.bat"this.copy_scripts은 []의 분할에서 constructued한다 이벤트를 사용하여 루프를 설정하고 계속하기보다는 콜백 메서드를 사용하여 비동기 대리자를 만들 것이라고 생각합니다. 프로세스가 완료되면 다시 RunCopyScript(...)으로 다시 전화하면됩니다. delegates on MSDN, and asynchronous programming을보십시오. 누군가가 Action으로이 작업을 수행 할 수있을 것이라고 확신합니다. 예를 들어 설명 할 정도로 잘 모릅니다.

또한 크로스 스레드 함수에서 gui 컨트롤 요소로 출력을 얻는 방법에 대한 간단한 조각을 보았습니다. 불행하게도 이전에 보았던 우아한 코딩 조각을 찾을 수 없습니다 ... 내가 그 코드를 가로 질러 실행하면에 링크를 게시 할 것입니다.

좋아요, 여기 제가 가지고있는 것이 있습니다 - 가치있는 것입니다. I 는 매우 정확합니다.을 믿습니다. 나는 프로세스를 제대로 시작하기 위해 모든 파일, 경로 등을 가지고 있지 않기 때문에 즉시 컴파일 될 것이라고 기대하지는 않습니다. 그리고 시뮬레이트 된 배치 파일을 Start()으로 설정하면 Process이 훨씬 더 많은 작업을 수행합니다. 나는 당신이 이것으로 일할 수 있어야하고 내가 위에서 제공 한 링크와 상호 참조한다면 당신이 원하는 것에 더 가깝게 할 수 있어야한다고 생각합니다.

필자는 필 요없는 코드 줄을 주석 처리했거나 이동했거나 인식하지 못했습니다. 또한 현재 귀하의 현재 try/catch 차단으로 아무 것도하지 않았습니다.

내가 언급 한 바와 같이
// same signature as the method to be called asynchronously 
delegate void RunScript(Int32 scriptIdx); 

// declare IAsyncResult 
IAsyncResult result; 

Process proc = null; 

private void copybutton_Click(object sender , EventArgs e) 
{ 
    InitializeBar(); 

    nbr_of_copy_exits_ = 0; 
    //this.RunCopyScript(this.nbr_of_copy_exits_); 
    RunScript start = new RunScript(RunCopyScript); 

    result = start.BeginInvoke(nbr_of_copy_exits_ , new AsyncCallback(CopyExited) , proc); 
    copybutton.Enabled = false // you don't want the button to be clicked again. 
} 

private void RunCopyScript(Int32 CopyScriptIdx) 
{ 
    try 
    { 
     proc = ObtainProcess(client_dest_dir_ + copy_scripts_[CopyScriptIdx]); 
     proc.EnableRaisingEvents = true; 
     //proc.Exited += new EventHandler(CopyExited); 
     proc.Start(); 
     progressBar.Value = ProgressInPercent(copy_scripts_.Count() , CopyScriptIdx); 
    } 
    catch (Exception ex) 
    { 
     UpdateControl(this.toolStripStatusLabel1, "Error involving " + copy_scripts_[CopyScriptIdx] + ": " + 
      ex.Message); 
     copybutton.BackColor = Color.Red; 
    } 
    //return; 
} 

void CopyExited(IAsyncResult iaRes) 
{ 
    AsyncResult result = (AsyncResult)iaRes; 
    RunScript caller = (RunScript)result.AsyncDelegate; 

    Process senderProcess = (Process)iaRes.AsyncState; 
    caller.EndInvoke(iaRes); 

    if (++this.nbr_of_copy_exits_ == this.copy_scripts_.Count()) 
    { 
     UpdateControl(toolStripStatusLabel1 , "Copying COMPLETE."); 
     copybutton.Enabled = true; // enable the button now that we're done 
    } 
    else 
    { 
     // start the process all over again 
     iaRes = caller.BeginInvoke(this.nbr_of_copy_exits_ , new AsyncCallback(CopyExited) , proc); 
    } 
} 

private void UpdateControl(ToolStripStatusLabel tssl , String text) 
{ 
    Invoke((MethodInvoker)delegate 
    { 
     tssl.Text = text; 
     progressBar.Value = 0; 
    }); 

    //tssl.Refresh(); 'System.Windows.Forms.ToolStripStatusLabel' does not contain a definition for 'Refresh'... 
} 

, 내가 비동기 수 있습니다 확신 액션 위임을 사용하여 더 우아한 구현이있다. 나는 누군가가 모범을 보여주기를 바랍니다.

+0

여러분의 작업에 큰 감사를 드렸습니다. 나는 당신의 방법을 시도했지만 불행하게도 같은 결과를 얻었습니다. 하지만 당신의 방법은 아직 시작하지 않은 것들을 사용합니다 : Begin/EndInvoke, delegate definition, IAsync 등. 나는 그들을 곧 사용할 것이다. 감사. – Joe

+0

@ 조 : 나는 당신을 돕기 위해 얼마나 가까이에있을 수 있을지 확신하지 못했지만 노력의 가치가 있다고 생각했습니다. – IAbstract

+0

그것은 정말로 있었다. 나는 아직 해결되지 않은 작은 결함 (즉, 앱 구성 파일이 처음부터 변경 될 가능성이 없으며, 잘못된 항목이 있음)을 언제든지 새로운 방식으로 교환 할 것입니다. 그것은 내가 절대적으로 사용할 좋은 정보였습니다. 우리는 '독단적 인 욕구'를 함께 지을 필요가 있습니다. 쉬운 일은 아니었다.) – Joe

관련 문제