2014-09-11 13 views
0

두 스레드가 같은 로그에 쓰고 오류가 발생하는 이중 스레드 C# 응용 프로그램이 있습니다.다중 스레드 C# 응용 프로그램 로그 파일 잠금 문제

'The process cannot access the file 'logfile.log' because it is being used by another process.' 

저는 C#과 멀티 스레딩에 다소 익숙하기 때문에 누구나 올바른 방향으로 나를 가리킬 수 있다면 많은 도움이 될 것입니다.

+0

특정 도움이 필요하면 코드를 더 게시하십시오. 그러나 일반적인 대답은 쓰기 전에 객체에 뮤텍스 또는 synclock을 사용하는 것입니다. – xDaevax

+0

로깅이 그렇게 쉬운 것처럼 보이지는 않습니다. 멀티 스레딩은 항상 생각보다 어렵습니다. [log4net] (http://logging.apache.org/log4net/)과 같은 무료 라이브러리 사용 –

+0

로깅 엔진은 무엇입니까? 핸드 메이드인가요? 이 경우에는 동시 액세스를 시도하지 마십시오. 대기열이있는 스레드 안전 로거와 쓰기를위한 보조 배경 스레드를 만듭니다 (비동기로 만들기 위해). 일반적으로 I/O에 관한 것이면 ... "지연 및 재시도"패턴을 사용하면 언젠가 어떤 일이 발생할 것이므로 반드시 필요합니다. –

답변

2

오류 메시지는 해당 파일이 스레드가 아닌 프로세스에 의해 열려 있음을 나타냅니다. 앱을 실행할 때마다 파일이 제대로 닫히고 있습니까?

일반적으로 응용 프로그램 내에서 공유 리소스에 대한 액세스를 제어하려면 잠금을 사용해야합니다. 당신이 로그() 함수와 LogWriter 클래스가있는 경우 예를 들어, 아니 대기와 최소한의 구현은 다음과 같습니다

public class LogWriter 
{ 
private readonly object _lock = new object; 

public void Log(string message) 
{ 
    lock(_lock) 
    { 
     //write message to log file 
     string appName = Path.GetFileNameWithoutExtension(Environment.GetCommandLineArgs()[0]); 
     StreamWriter sw = new StreamWriter(Environment.CurrentDirectory + Path.DirectorySeparatorChar + appName + ".log", true); 
     sw.WriteLine(string.Format("{0:u} {1}", DateTime.Now, message)); 
     sw.Flush(); 
     sw.Close(); 
    } 
} 

lock(_lock)는 한 번에 하나의 스레드 만에 파일에 액세스 보장합니다. sw.Close()은 프로세스가 종료 될 때 파일이 열리지 않도록합니다.

+1

"다른 프로세스"라는 문구는 일반적입니다. 파일이 별도의 프로세스에있는 스레드에 의해 잠겨 있는지 또는 프로세스의 스레드에 의해 잠겨 있는지 여부를 알 수 있습니다. 또한 명시 적으로 닫지 않으면 프로세스가 종료 될 때 파일 시스템이 자동으로 파일을 닫습니다. 버퍼를 플러시하지 않지만 파일을 닫을 것입니다. –

2

오류 메시지는 여러 다른 스레드에서 작성자를 만들 수 없음을 나타냅니다. 스레드간에 파일에 대한 액세스를 동기화하는 방법을 찾아야합니다. 즉, 다른 모든 스레드가 파일을 처리 할 때까지 한 스레드가 파일에 액세스하려고 기다리는 지 확인하거나 단일 스레드를 지정할 수 있습니다 스레드가 해당 파일에 액세스 할 책임이 있고 다른 스레드가 해당 파일에 액세스하여 다른 스레드가 해당 스레드에 대해 수행하도록 요청해야합니다.

+0

불행히도 그들은 모두 로그에 쓸 수 있어야합니다. – asdf

+4

@BadKarma 반드시 그렇지는 않습니다. 예를 들어, 그들은 각각 하나의 스레드가 소비하는 메모리 대기열의 스레드 안전 항목에 항목을 추가하여 파일에 내용을 쓸 수 있습니다. 여러 스레드가 내용을 파일에 기록해야 함을 나타낼 수 있어야한다고해서 실제로 작성해야한다는 의미는 아닙니다. – Servy

1

병렬 스레드에서 액세스 할 수있는 목록 (또는 원하는 데이터 구조)을 만들어야합니다. 그런 다음 각 스레드의 해당 목록에 레코드를 추가하십시오.

lock (yourList) { 
    // here you can add items to the List 
    } 

완료되면 목록을 파일로 덤프하십시오. 또는 각 스레드마다 새 List를 작성한 다음 다시 모두 리턴 한 다음 모든 목록을 하나로 결합하십시오. 대체 솔루션으로 또는 데이터베이스를 사용하여 테이블에 레코드를 추가 (가장 논리적 인 해결책)

  1. 모든 스레드 목록 글로벌 목록
  2. 패스를 생성하고 (위의 예)를 고정 그것을 쓰기. 목록을 해제 빈, 파일에 쓸 목록
  3. 를, 목록을 잠그고는
  4. 지연 후, 무한 루프 내부 지연
  5. 또 다른 무한 루프 스레드를 생성 잠금을 해제 모든 데이터를 얻을 수
관련 문제