2011-10-05 8 views
0

나는 최근에 StatusBar 컨트롤에 포함 된 ToolStripProgressBar 컨트롤을 통해 상태 표시 줄에 다른 스레드의 진행 상태를 표시하고자하는 응용 프로그램에서 작업했습니다. 이 코드를 추가하려고 시도하기 전에 원래 ToolStripStatusLabel 컨트롤의 텍스트를 변경하는 코드가 있었고이 작업을 수행하기 위해 대리자와 함께 Invoke 메서드가 사용되었습니다. 그러나 나는 이것을 ToolStripProgressBar으로 시도했을 때 상태 표시 줄의 Invoke 메서드 호출이 알림없이 실패했음을 발견했습니다 (오류도 예외도 없음). 그 이후로 배웠던 점은이 방법으로 진행 막대를 사용하려면 BackgroundWorker 컨트롤을 사용해야한다는 것입니다. 그래서 내 코드는 작동하지만, 왜 내가 이미 작동하는 것 같던 Invoke 메서드를 사용할 수 없었는지 이해할 수 없다. 하지 않았다 어떤 일을하고 무엇을ToolStripProgressBar에 StatusBar.Invoke 메서드가 작동하지 않는 이유는 무엇입니까?

몇 가지 예 :

이는이 InvokeRequired 속성을 작동하지 않았다 예에서

public delegate void incrementProgressBar(int value); 
public incrementProgressBar incrementProgressBarDelegate; 
public void incrementProgressBarMethod(int value){ 
     if(statusbar.InvokeRequired){ 
      statusbar.Invoke(incrementProgressBarDelegate, new Object[] {value}); 
     }else{ 
      toolstripProgress.Increment(value); 
     } 
} 

를 작동하지 않았다

public delegate void changeStatusMessage(String message); 
public changeStatusMessage changeStatusMessageDelegate; 
public void changeStatusMessageMethod(String message){ 
     if(statusbar.InvokeRequired){ 
      statusbar.Invoke(changeStatusMessageDelegate, new Object[] {message}); 
     }else{ 
      toolstripLabel.Text = message; 
     } 
} 

근무 이 참이므로 Invoke 메서드가 호출되고 아무 일도 일어나지 않습니다. 어디에서 내가 InvokeRequired이 거짓이고 따라서 Increment 메서드가 실행되도록 incrementProgressBarMethod에 다시 전화 할 것으로 예상했는지.

왜 이것이 작동하지 않는지 알고 싶습니다. 내가 이미 BackgroundWorker을 사용하도록 수정했다고 말했기 때문에 설명을 원합니다.

+1

. Control.Invoke()는 주 스레드가 막히면 쉽게 교착 상태가되어 "아무 일도 일어나지 않습니다"는 흔한 일이 아닙니다. BackgroundWorker로 고정하십시오. –

+0

"쉬운"설명을 원한다고 말한 적은 없었습니다. 간단히 말해서 Control.Invoke()는 교착 상태를 일으킬 수 있으므로 그 이유를 이해하기에 충분하지 않습니다. Control.Invoke()가 이유 때문에 제공됩니다. 동일한 코드로 비슷한 방식으로 처리되는 컨트롤이 문제없이 작동 할 때 왜이 컨트롤에 사용할 수 없습니까? – JRSofty

+0

문제를 증명하고 누구나 테스트 할 수있는 게시판 코드를 작성하면 답변을 얻을 수 있습니다. –

답변

0

Invoke는 postmessage API를 호출하고 Windows 메시지에 메시지를 대기열에 넣습니다. UI 스레드가 차단되면 푸시 큐에 대기중인 메시지가 없기 때문에 교착 상태가 발생할 수 있습니다. 아무 일도 일어나지 않습니다. 필요한 invoke의 다른 쪽은 해고되지 않으며, 어떤 것이 기다리고 있다면, bang, deadlock.

Invoke에주의해야하는 이유가 여기에 있습니다.

How to invoke a function on parent thread in .NET?

그러나 문제는 위임의 생성에, 그것은 널 대표, 당신은 다른 방법 때문에, 부하 시스템 것, 그것이 호출에 의해 호출되고 있음을 동일한 스레드에서 대리자를 만들 필요가 델리게이트 (포인터)를 마샬링 할 때 실패합니다.

private void changeStatusMessageMethod(String message) 
    { 
     if (this.InvokeRequired) 
     { 
      var changeStatusMessageDelegate = new changeStatusMessage(changeStatusMessageMethod); 
      this.Invoke(changeStatusMessageDelegate, new Object[] { message }); 
     } 
     else 
     { 
      toolstripLabel.Text = message; 
     } 
    } 
    delegate void incrementProgressBar(int value); 
    private void incrementProgressBarMethod(int value) 
    { 
     if (this.InvokeRequired) 
     { 
      var incrementProgressBarDelegate = new incrementProgressBar(incrementProgressBarMethod); 
      this.Invoke(incrementProgressBarDelegate, new Object[] { value }); 
     } 
     else 
     { 
      toolstripProgress.Increment(value); 
     } 
    } 

이 후에 .NET 프레임 워크 V4에서 작동 당신에게 쉽게 설명을 손 것 TSPB 특별한 거기에 아무것도

private void button1_Click(object sender, EventArgs e) 
    { 
     var t = new System.Threading.Thread(new System.Threading.ThreadStart(x)); 
     t.Start(); 
    } 

    private void x() 
    { 
     do 
     { 
      changeStatusMessageMethod(DateTime.Now.ToString()); 
      System.Threading.Thread.Sleep(1000); 
     } while (true); 
    } 

    private void button2_Click(object sender, EventArgs e) 
    { 
     var t = new System.Threading.Thread(new System.Threading.ThreadStart(y)); 
     t.Start(); 
    } 

    private void y() 
    { 
     do 
     { 
      incrementProgressBarMethod(1); 
      System.Threading.Thread.Sleep(1000); 
     } while (true); 
    } 
관련 문제