2009-08-31 5 views
1

아래 표시된 사용자 지정 TraceListener의 출력으로 사용하는 RichTextBox가 있습니다. 다른 사람이 디버그/추적 정보를 쓰는 경우 어려움이 있습니다. GUI 대화 상자도 디버그/추적 정보를 쓰려고합니다.RichTextBox에 사용자 지정 System.Diagnostics.TraceListener 출력이 중단되었습니다.

누구나 여기서 명백한 오류를 지적 할 수 있습니까? :

class MyTraceListener : TraceListener 
{ 
    private RichTextBox output; 

    public MyTraceListener (RichTextBox output) { 
     this.Name = "DebugTrace"; 
     this.output = output; 
    } 


    public override void Write(string message) { 
     Action append = delegate() { output.AppendText(message); }; 
     if (output.InvokeRequired) { 
      IAsyncResult result = output.BeginInvoke(append); 
      output.EndInvoke(result); 
     } else { 
      append(); 
     } 
    } 

    public override void WriteLine(string message) { 
     Action append = delegate() { output.AppendText(message + "\r\n"); }; 
     if (output.InvokeRequired) { 
      IAsyncResult result = output.BeginInvoke(append); 
      output.EndInvoke(result); 
     } else { 
      append(); 
     } 

    } 
} 

답변

1

여기 가능성이 일어나고있는 작업은 다음과 같습니다

  • 스레드 1 : EndInvoke을 가져옵니다(); GUI 스레드의 에서 대리인을 실행하기 위해 대기 중입니다.
  • GUI 스레드 ( 자물쇠 스레드 안전을 위해 사용 추적 시스템 AFAIK.) 어딘가 System.Diagnostics.Trace.WriteLine 에서 차단
  • 스레드 1을 다음 GUI 스레드가 차단되므로, 영원히 차단되며 대리인 실행을 완료 할 수 없습니다.

Invoke가 실행될 때까지 Invoke가 차단되기 때문에 Just Invoke를 호출하면 문제가 해결되지 않을 가능성이 높습니다.

호출 만 BeginInvoke는 잠금을 해결해야합니다. BeginInvoke는 GUI 스레드에 대한 비동기 호출을 시작하고 완료 될 때까지 기다리지 않고 추적 시스템을 종료하고 GUI 스레드를 차단 해제합니다. (EndInvoke를 호출하지 않는 것에 대한 확신이 없습니다.

+0

BeginInvoke 만 호출하면 교착 상태가 발생하는 것을 제외하고는 본질적으로 동일한 클래스를 작성했습니다. AFAIK에서는 EndInvoke를 호출 할 필요가 없습니다. do not는 inv의 결과를 신경 쓰지 않는다. 알았어. –

+0

글쎄, 그래서에 대한 다른 논의 EndInvoke 전화해야 나타냅니다. 그러나 여기서 일어나는 일들은 EndInvoke에서의 블로킹을 피하면서 정말로 잠그지 않습니다. –

0

BeginInvoke와 대조적으로 Control.Invoke를 사용해보십시오. IE :

class MyTraceListener : TraceListener 
{ 
     private RichTextBox output; 

     public MyTraceListener (RichTextBox output) { 
       this.Name = "DebugTrace"; 
       this.output = output; 
     } 


     public override void Write(string message) { 
       Action append = delegate() { output.AppendText(message); }; 
       if (output.InvokeRequired) { 
         output.Invoke(append); 
       } else { 
         append(); 
       } 
     } 

     public override void WriteLine(string message) { 
       Action append = delegate() { output.AppendText(message + "\r\n"); }; 
       if (output.InvokeRequired) { 
         output.Invoke(append); 
       } else { 
         append(); 
       } 

     } 
} 
+0

모든 샘플 사용 MyTraceListener? – Kiquenet

0

이 방법을 사용하면 어떻게됩니까?

public override void Write(string message) { 
    if (this.output.InvokeRequired) 
    { 
     this.output.Invoke((MethodInvoker)delegate 
     { 
      this.output.AppendText(message); 
     }); 
    } 
    else 
    { 
     this.output.AppendText(message); 
    } 
} 
0

간단한 제작자/고객 대기열을 사용 하시길 권합니다. 트레이스 쓰기에 대한 응답은 대기열에 문자열을 추가 한 다음 데이터를 표시하는 폼에서 System.Windows.Forms.Timer()를 사용하여 큐를 비우고 텍스트를 표시 할 수 있습니다. 그렇지 않으면 실행중인 프로그램에서 문제 및/또는 지연이 발생할 수 있습니다.

관련 문제