2016-09-09 2 views
0

도와 주셔서 감사합니다. 이번에는 필자가 작성한 프로그램 (C#)에 흥미로운 문제가있어서 조언을 듣고 싶습니다. 일반 프로그램 (멀티 스레드가 아닌)을 작성하고 있지만 타이머 (System.Timers.Timer)를 추가했습니다.타이머, 파일 및 경쟁 조건?

또한 파일에 쓸 StreamWriter를 사용하고 있습니다. 나는 이것을 이렇게 열어 둔다.

이 파일이 존재하면, 그것이 존재하지 않으면 추가한다.

는 나중에 나는 내가 모두 주요 기능에서 타이머에 의해 호출되는 함수에서 스트림에 쓰기, 그러나이

logStream.WriteLine(message); 

같은 파일에 작성합니다.

문제 증상 내 프로그램은 내가 세척 또는 다른 시간 "폐쇄 된 파일에 액세스 할 수 없습니다"라고 말하는 스트림을 쓸 때 가끔 오류를 던지고있다

는 "폐쇄 TextWriter에 액세스 할 수 없습니다 ... 파일이 문제없이 기록되는 유지, 그러나 호기심

(?는 "TextWriter를"무엇입니까). (심지어 "폐쇄 된 파일에 액세스 할 수 없습니다"메시지가되어 폐쇄 된 파일로 작성)

내가 Timer의 내부 동작에 익숙하지 않다. (나는 sep를 실행한다고 생각한다. arate 스레드?)

내 질문이

입니다 그것은 여러 스레드에서 StreamWriter를 사용할 수 있습니까? (이 경우 메인 타이머와 타이머 1) 경쟁 조건이나 이와 같은 문제가 발생할 수 있습니까?


한가지 더 : 나는 로직 실수 닫기를 만들어 파일을 내가 그것을 기록 할 때마다 다시 엽니 다. 예, 그것은 실수입니다. 나는 그것을 바로 잡아야합니다. 하지만 아마도이 문제를 해결하면 위에서 설명한 오류가 사라져 더 심각한 결함을 숨길 수 있습니다.

내 의심은 내가 파일 나는 그것에 쓰는 모든 시간을 폐쇄하고 개방하고 있기 때문에, 아마 두 스레드가

어떤 도움을 크게

+0

다음 질문 중 하나 : StreamWriter는 특정 TextWriter입니다. –

+2

로깅 구현을 만들려고하십니까? 왜 당신이 사용하지 마십시오.NET의 내장 진단 API 또는 log4net과 같은 로깅 라이브러리? 로깅 라이브러리는 여러 스레드의 로그 요청을 수락해야하지만 로그 파일을 손상시키지 않으면 서 모든 항목을 올바르게 작성해야합니다. –

답변

1
을 이해할 수있을 것이다 잘못된 시간에 액세스하려고한다는 것입니다

이 시나리오에서 파일을 닫고 열면 의심스러운 경쟁 조건이 생성됩니다. 스트림을 열어 두어 스레드에 객체를 전달할 수 없기 때문에 다른 스레드에서 호출하는 경우 비슷한 문제가 발생할 수 있습니다. 가장 좋은 솔루션은 보내는 메시지를 쓰는 스레드 안전 메서드를 사용하는 것입니다.

잠금은 클래스의 모든 인스턴스에서 액세스 할 수 있어야하기 때문에 메소드가 정적입니다.

private static ReaderWriterLockSlim readerWriterLockSlim = new ReaderWriterLockSlim(); 

public static void AppendToFile(string path, string text) 
{ 
    // Set to locked (other thread will freeze here until object is unlocked 
    readerWriterLockSlim.EnterWriteLock(); 

    try 
    { 
     // Write that will append to the file 
     using (StreamWriter sw = File.AppendText(path)) 
     { 
      // append the text 
      sw.WriteLine(text); 
      sw.Close(); 
     } 
    } 
    finally 
    { 
     // Clear the lock 
     readerWriterLockSlim.ExitWriteLock(); 
    } 
} 
+1

더 나은 아직 로깅 라이브러리를 사용하십시오. 또는 ActionBlock 은 여러 스레드의 메시지를 대기열에 넣고 간단한 작성기를 사용하여 하나씩 씁니다. –