2009-11-09 8 views
2

여러 스레드에서 파일에 로깅하는 동안 경쟁 조건과 같은 느낌이 들었습니다.경쟁 조건/TextWriterTraceListener

1) 응용 프로그램의 여러 스레드에서 공유하는 사용자 지정 로거 클래스 (ConfigurableTraceLogger)가 있습니다. 이 주요 핵심 기능

protected void TraceData(String category, TraceEventType type, EventId id, string prefix, string format) 
{ 
    foreach (TraceListener item in _listeners) 
    { 
     IConfigurableTraceListener cl = item as IConfigurableTraceListener; 

     if (cl != null && cl.Category == category.ToLower()) 
     { 

      if (DisplayMethodName) 
       item.TraceData(new TraceEventCache(), _instanceName, type, (int)id, prefix + format); 
      else 
       item.TraceData(new TraceEventCache(), _instanceName, type, (int)id, format); 

      item.Flush(); 
     } 
    } 
} 

에 대한 모든 호출하면 모음 _listeners에 내 수업은 단순히 다른 TraceListner-derved 클래스를 저장하고 볼 수있는 래퍼 기능을 많이 가지고 있어요. 기본적으로 콘솔 및 텍스트 파일 수신기 만 있습니다. 어떤 TraceData는 카테고리 이름 (즉, 로깅 시작)을 취해 올바른 리스너를 찾습니다. 모든 리스너 설정 파일 이름

에 의해 정의됩니다 지금은 또한 사용자 정의 클래스는 하나 개의 속성을 제외하고 아무것도 무시하지 않는다는 수집

public class ConfigurableTextWriterTraceListener : TextWriterTraceListener, IConfigurableTraceListener 

에 내 사용자 정의 리스너가 있습니다.

protected override string[] GetSupportedAttributes() 
{ 
    return new string[] { "category" }; 
} 

내가 말하고 내가 전화

  item.TraceData(new TraceEventCache(), _instanceName, type, (int)id, prefix + format); 

예외에 예외 를 얻을 수 5 ~ 10 분 후 내 응용 프로그램을 시작할 때 : 복사하는 동안

"가능성있는 I/O의 경쟁 조건이 감지 다중 스레드 응용 프로그램에서 스트림은 TextReader 또는 TextWriter의 Synchronized 메서드에서 반환되는 스레드 안전 래퍼와 같이 스레드로부터 안전한 방법으로 액세스해야합니다. 또한이 I/O 패키지는 기본적으로 스레드로부터 안전하지 않습니다. StreamWriter 및 StreamReader와 같은 클래스에 적용됩니다. " I가 0보다 작을 수 없습니다

카운트

item.TraceData(new TraceEventCache(), _instanceName, type, (int)id, prefix + format); 

예외로 동일한 통화 시간의 두 번째 예외를 많이 받고 계속 그 후

. System.IO.StreamWriter.Write (문자열 값)의 System.String.CopyTo (Int32 sourceIndex, Char [] 대상, Int32 destinationIndex, Int32 개수)에서 스택 추적 : " " System.Diagnostics.TraceListener.TraceData에서 System.Diagnostics.TextWriterTraceListener.Write (String message)에서 System.Diagnostics.TraceListener.WriteHeader (String source, TraceEventType eventType, Int32 id) \ r \ n에 n을 입력하십시오. (TraceEventCache eventCache Jfc.Configuration.ConfigurableTraceLogger.TraceData (문자열 범주, TraceEventType 유형, EventId ID, 문자열 접두사, 문자열 형식, 객체 [] 인수)의 "rsn", "문자열 소스, TraceEventType 이벤트 유형, Int32 ID, 객체 데이터)"

TraceData를 호출해도 클래스가 스레드로부터 안전하지 않은 것으로 보입니다. 하지만 ConfigurableTextWriterTraceListener는 결국 스레드로부터 안전하다고합니다. 그러나 런타임에 에서 TextWriterTraceListener 파생 클래스의 IsThreadSafe 속성을 확인하고 false로 설정했습니다. 나는 문제가 어디 있는지 알아 내려고 노력하고있다.

+0

한, 당신은 그것을 남길 수 있습니다 사용중인 언어 –

+0

여기에 수정 버튼이 없습니다. 어디 있니? 아니면 다음 게시물을 의미합니까? –

답변

1

즉, TraceListener는 스레드로부터 안전하지 않으며 여러 스레드에서 액세스 할 때 중단됩니다. 리스너를 스레드로부터 안전하게 보호하거나 하나의 스레드 만 특정 인스턴스에 액세스하도록하는 방법을 찾아야합니다.

스레드를 안전하게 만드는 한 가지 방법은 동기화 된 대기열을 사용하고 '진짜'traceListener가 대기열에서 데이터 항목을 대기열에 추가하고 모든 스레드를 대기열에서 제외하고 별도의 스레드에 써내는 것입니다.

또한 청취자 여러분의 사전에주의해야 - 사전을 업데이트하는 스레드로부터 안전하지 않습니다,하지만 마지막 업데이트를 적용하기 전에 당신이 그것을 액세스하지 경우에 태그를하시기 바랍니다

+0

글쎄 고마워! 동의합니다. 큐 기반 스레드 안전 로거를 만들어야합니다. 하지만 여전히 대답이 없습니다 - 왜 TextWriterTraceListner 파생 TraceData 메서드에서 MSDN은 이 클래스는 스레드로부터 안전하다고 말했습니까? 많은 스레드가이 메서드를 안전하게 호출 할 수 있다는 것을 의미한다고 생각합니다. 그러나 그들이 할 수없는 것처럼 보입니다. 추신 : 구성 파일에서 .NET에 의해 생성 된 사전을 만지지는 않으며 로깅은 거의 시작됩니다. –

+0

'이 형식의 모든 공용 static (Visual Basic의 경우 Shared) 멤버는 스레드로부터 안전합니다. 모든 인스턴스 멤버는 스레드 안전성을 보장하지 않습니다. '이것은 TextWriterTraceListener 클래스 도움말에서 직접 가져옵니다. – mfeingold

+0

오른쪽 - 결코 정적 인 것은 아닙니다. 감사. –