문제

웹 서비스에서 가져와 웹 응용 프로그램 내에서 로컬로 캐시된 일부 데이터를 XML로 표현한 파일이 있습니다.아이디어는 이 데이터가 매우 정적이지만 그냥 ~할 것 같다 변화.그래서 파일에 캐시하도록 설정하고 모니터를 연결하여 삭제되었는지 확인했습니다.삭제되면 파일은 소스에서 새로 고쳐지고 다시 작성됩니다.

하지만 이제 문제가 발생했습니다. 분명히 다중 스레드 환경에서는 파일을 계속 읽고 쓰는 동안 데이터에 액세스하려고 시도하기 때문에 문제가 발생하기 때문입니다.

잠글 개체를 추가했는데 읽기/쓰기 중에 항상 잠겨 있기 때문에 혼란스럽습니다.다른 스레드에서 액세스를 시도하면 잠금이 해제될 때까지 "대기"하라는 메시지가 표시된다는 것이 제가 이해한 것입니까?

알려드리자면, 저는 멀티스레드 개발을 처음 접하는 사람이므로 이것이 저의 실수라는 점을 기꺼이 받아들입니다. :)

  • 뭔가 빠졌나요?
  • 멀티스레드 환경에서 가장 좋은 파일 액세스 전략은 무엇입니까?

편집하다

죄송합니다. 이것이 사용 중이라고 말했어야 했습니다. ASP.NET 2.0 :)

도움이 되었습니까?

해결책

다음은 파일이 다른 프로세스에 의해 잠겨 있지 않은지 확인하는 데 사용하는 코드입니다.100% 완벽하지는 않지만 대부분의 경우 작업을 완료합니다.

    /// <summary>
    /// Blocks until the file is not locked any more.
    /// </summary>
    /// <param name="fullPath"></param>
    bool WaitForFile(string fullPath)
    {
        int numTries = 0;
        while (true)
        {
            ++numTries;
            try
            {
                // Attempt to open the file exclusively.
                using (FileStream fs = new FileStream(fullPath,
                    FileMode.Open, FileAccess.ReadWrite, 
                    FileShare.None, 100))
                {
                    fs.ReadByte();

                    // If we got this far the file is ready
                    break;
                }
            }
            catch (Exception ex)
            {
                Log.LogWarning(
                   "WaitForFile {0} failed to get an exclusive lock: {1}", 
                    fullPath, ex.ToString());

                if (numTries > 10)
                {
                    Log.LogWarning(
                        "WaitForFile {0} giving up after 10 tries", 
                        fullPath);
                    return false;
                }

                // Wait for the lock to be released
                System.Threading.Thread.Sleep(500);
            }
        }

        Log.LogTrace("WaitForFile {0} returning true after {1} tries",
            fullPath, numTries);
        return true;
    }

분명히 애플리케이션에 맞게 시간 초과 및 재시도를 조정할 수 있습니다.나는 이것을 작성하는 데 시간이 걸리는 거대한 FTP 파일을 처리하는 데 사용합니다.

다른 팁

다음과 같이 저장된 객체를 잠그는 경우 공전 그러면 동일한 애플리케이션 도메인의 모든 스레드에 대해 잠금이 작동해야 하지만 문제가 되는 행을 살펴볼 수 있도록 코드 샘플을 업로드해야 할 수도 있습니다.

즉, 한 가지 생각은 IIS가 다음에서 실행되도록 구성되어 있는지 확인하는 것입니다. 웹가든 모드(예:응용 프로그램을 실행하는 프로세스가 두 개 이상) 잠금 논리가 손상될 수 있습니다.뮤텍스를 사용하면 이러한 상황을 해결할 수 있지만 단일 프로세스에서 실행되도록 응용 프로그램을 재구성하는 것이 더 쉬울 것입니다. 하지만 잠재적으로 영향을 미칠 수 있으므로 웹 가든 설정을 조작하기 전후에 성능을 확인하는 것이 현명할 것입니다. 성능.

임시 이름("data.xml_TMP")을 사용하여 파일을 생성할 수 있으며, 준비가 되면 이름을 예상되는 이름으로 변경할 수 있습니다.이렇게 하면 준비되기 전에는 다른 프로세스에서 액세스할 수 없습니다.

좋아, 나는 이 작업을 해왔고 결국 여러 스레드에서 내 코드를 기본적으로 망치는 스트레스 테스트 모듈을 만들었습니다.관련 질문 보기).

이 시점부터 내 코드에서 구멍을 찾는 것이 훨씬 쉬웠습니다.내 코드가 실제로 멀리 떨어져 있지는 않았지만 기본적으로 읽기/쓰기 작업이 쌓이게 하는 입력할 수 있는 특정 논리 경로가 있었습니다. 즉, 시간 내에 지워지지 않으면 가 붐!

그것을 꺼내고 스트레스 테스트를 다시 실행했는데 모두 잘 작동했습니다!

그래서 난 정말 아무것도 하지 않았어 특별한 내 파일 액세스 코드에서 내가 사용한 것을 확인했습니다. lock 적절한 경우 진술(예:읽거나 쓸 때).

사용하는 것은 어떻습니까? AutoResetEvent 스레드 간에 통신하려면?대략 8GB 파일을 생성하는 콘솔 앱을 만들었습니다. createfile 방법을 선택한 다음 해당 파일을 main 방법

 static AutoResetEvent waitHandle = new AutoResetEvent(false);
    static string filePath=@"C:\Temp\test.txt";
    static string fileCopyPath=@"C:\Temp\test-copy.txt";
    static void Main(string[] args)
    {
        Console.WriteLine("in main method");
        Console.WriteLine();
        Thread thread = new Thread(createFile);
        thread.Start();

        Console.WriteLine("waiting for file to be processed ");
        Console.WriteLine();
        waitHandle.WaitOne();
        Console.WriteLine();

        File.Copy(filePath, fileCopyPath);
        Console.WriteLine("file copied ");

    }


    static void createFile()
    {

        FileStream fs= File.Create(filePath);            
        Console.WriteLine("start processing a file "+DateTime.Now);
        Console.WriteLine();
        using (StreamWriter sw = new StreamWriter(fs))
        {
            for (long i = 0; i < 300000000; i++)
            {
                sw.WriteLine("The value of i is " + i);

            }
        }
        Console.WriteLine("file processed " + DateTime.Now);
        Console.WriteLine();

        waitHandle.Set();
    }
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top