IOException : 프로세스가 'file path'파일을 다른 프로세스에서 사용 중이므로 파일에 액세스 할 수 없습니다.


172

나는 약간의 코드를 가지고 있고 그것이 실행될 때 IOException,

프로세스가 다른 프로세스에서 사용 중이므로 'filename'파일에 액세스 할 수 없습니다.

이것은 무엇을 의미하며 이에 대해 무엇을 할 수 있습니까?


1
파일을 사용하는 다른 프로세스를 찾는 방법 은 이 질문 을 참조하십시오 .
stomy

답변:


274

원인이 무엇입니까?

오류 메시지는 매우 분명합니다. 파일에 액세스하려고하는데 다른 프로세스 (또는 동일한 프로세스)가 파일로 무언가를하고 있기 때문에 액세스 할 수 없습니다 (그리고 공유를 허용하지 않았습니다).

디버깅

특정 시나리오에 따라 해결하기가 매우 쉬울 수 있습니다. 좀 봅시다

프로세스는 해당 파일에 액세스 할
있는 유일한 프로세스입니다. 다른 프로세스는 자신의 프로세스입니다. 프로그램의 다른 부분에서 해당 파일을 열었다는 것을 알고 있다면, 매번 사용 후 파일 핸들을 올바르게 닫았는지 확인해야합니다. 이 버그가있는 코드의 예는 다음과 같습니다.

var stream = new FileStream(path, FileAccess.Read);
var reader = new StreamReader(stream);
// Read data from this file, when I'm done I don't need it any more
File.Delete(path); // IOException: file is in use

다행히도를 FileStream구현 IDisposable하므로 모든 코드를 using명령문으로 쉽게 묶을 수 있습니다 .

using (var stream = File.Open("myfile.txt", FileMode.Open)) {
    // Use stream
}

// Here stream is not accessible and it has been closed (also if
// an exception is thrown and stack unrolled

이 패턴은 또한 예외가 발생할 경우 파일이 열린 상태로 유지되지 않도록합니다 (파일이 사용중인 이유 일 수 있습니다. 문제가 발생하여 아무도 닫지 않았습니다 . 예를 보려면 이 게시물 참조 ).

모든 것이 정상으로 보이면 (예외의 경우에도 열려있는 모든 파일을 항상 닫을 수 있음) 여러 작업 스레드가있는 경우 두 가지 옵션이 있습니다. 코드를 재 작업하여 파일 액세스를 직렬화합니다 (항상 가능한 것은 아니며 항상 그렇지는 않습니다) 원하는) 또는 재시도 패턴을 적용 하십시오 . I / O 작업의 일반적인 패턴입니다. 무언가를 시도하고 오류가 발생하면 기다렸다가 다시 시도하십시오 (예를 들어, Windows Shell이 ​​파일을 사용하고 있음을 알리는 데 시간이 걸리는 이유를 스스로에게 묻었습니까?) 삭제할 수 없습니까?). C #에서는 구현하기가 매우 쉽습니다 ( 디스크 I / O , 네트워킹데이터베이스 액세스에 대한 더 나은 예제도 참조하십시오 ).

private const int NumberOfRetries = 3;
private const int DelayOnRetry = 1000;

for (int i=1; i <= NumberOfRetries; ++i) {
    try {
        // Do stuff with file
        break; // When done we can break loop
    }
    catch (IOException e) when (i <= NumberOfRetries) {
        // You may check error code to filter some exceptions, not every error
        // can be recovered.
        Thread.Sleep(DelayOnRetry);
    }
}

StackOverflow에서 자주 발생하는 일반적인 오류에 유의하십시오.

var stream = File.Open(path, FileOpen.Read);
var content = File.ReadAllText(path);

이 경우 ReadAllText()파일이 사용 중이기 때문에 실패합니다 ( File.Open()이전 줄에서). 파일을 미리 여는 것은 불필요 할뿐만 아니라 잘못된 것입니다. 같은 모든 적용 File반환하지 않는 기능 핸들을 작업중인 파일 : File.ReadAllText(), File.WriteAllText(), File.ReadAllLines(), File.WriteAllLines()과 (같은 다른 File.AppendAllXyz()기능) 모든 열고 스스로 파일을 닫습니다.

프로세스가 해당 파일에 액세스 할 수있는 유일한 프로세스가 아닙니다 프로세스가 해당 파일에 액세스하는 유일한 프로세스가 아닌
경우 상호 작용이 더 어려울 수 있습니다. 재시도 패턴 (파일이 다른 사람이 열 수 없습니다하는 경우는 있지만, 당신은 확인 프로세스 탐색기와 같은 유틸리티를 필요로한다 도움이 될 것입니다 누가 하고있는 ).

피하는 방법

해당되는 경우 항상 using 문을 사용 하여 파일을 엽니 다. 이전 단락에서 말했듯이 많은 일반적인 오류를 피하는 데 적극적으로 도움이됩니다 ( 이 게시물 을 사용하지 않는 방법 에 대한 예는 이 게시물 참조 ).

가능하면 특정 파일에 대한 액세스 권한을 가진 사람을 결정하고 잘 알려진 몇 가지 방법을 통해 액세스를 중앙 집중화하십시오. 예를 들어, 프로그램이 읽고 쓰는 데이터 파일이있는 경우 모든 I / O 코드를 단일 클래스 안에 넣어야합니다. 디버그가 쉬워집니다 (항상 중단 점을두고 누가 무엇을하고 있는지 알 수 있기 때문에). 또한 다중 액세스를위한 동기화 지점 (필요한 경우)이 될 것입니다.

I / O 작업이 항상 실패 할 수 있다는 것을 잊지 마십시오. 일반적인 예는 다음과 같습니다.

if (File.Exists(path))
    File.Delete(path);

경우 누군가가 후 파일을 삭제 File.Exists()하지만, 전에 File.Delete(), 다음은을 던질거야 IOException당신이 잘못 안전 느낄 수있는 장소에.

가능할 때마다 재시도 패턴을 적용 FileSystemWatcher하고을 사용하는 경우 연기 조치를 고려하십시오 (알림을받을 수는 있지만 애플리케이션이 해당 파일에서만 독점적으로 작동 할 수 있음).

고급 시나리오
항상 쉬운 것은 아니므로 다른 사람과 액세스를 공유해야 할 수도 있습니다. 예를 들어 처음부터 끝까지 읽고 쓰는 경우 최소한 두 가지 옵션이 있습니다.

1) 스레드 안전하지FileStream 않기 때문에 적절한 동기화 기능으로 공유하십시오 . 참조 예제는 게시물.

2) FileShare열거를 사용하여 다른 프로세스 (또는 자체 프로세스의 다른 부분)가 동일한 파일에 동시에 액세스 할 수 있도록 OS에 지시하십시오.

using (var stream = File.Open(path, FileMode.Open, FileAccess.Write, FileShare.Read))
{
}

이 예제에서는 쓰기 위해 파일을 열고 읽기 위해 공유하는 방법을 보여주었습니다. 읽고 쓸 때 겹치면 데이터가 정의되지 않거나 유효하지 않습니다. 읽을 때 처리해야하는 상황입니다. 또한 이것은 stream스레드 안전에 액세스하지 않으므로 액세스가 어떻게 든 동기화되지 않으면이 객체를 여러 스레드와 공유 할 수 없습니다 (이전 링크 참조). 다른 공유 옵션을 사용할 수 있으며 더 복잡한 시나리오를 엽니 다. 자세한 내용은 MSDN 을 참조하십시오.

일반적으로 N 프로세스는 동일한 파일에서 모두 읽을 수 있지만 하나만 작성해야합니다. 제어 된 시나리오에서는 동시 쓰기를 활성화 할 수도 있지만이 답변의 텍스트 단락에서는 일반화 할 수 없습니다.

다른 프로세스에서 사용하는 파일의 잠금해제 할 수 있습니까? 항상 안전하지는 않지만 쉽지는 않지만 가능합니다 .


코드에 어떤 문제가 있는지 모르고 블록을 사용하지만 파일을 삭제하려고 할 때 파일이 사용 중이라는 오류가 여전히 있습니다.
Jamshaid Kamran

아니요, 실제로 타이머 옆에 타이머 컨트롤이 있습니다. 타이머를 다시 호출하면 예외가 발생합니다. 기본적으로 파일을 다른 텍스트 파일로 해독하고 새로 생성 된 파일을 삭제 한 후 삭제시 예외가 발생합니다!
Jamshaid Kamran

3
@ جمشیدکامران 왜 코드에 내용이 담긴 파일을 만든 다음 삭제합니까? 그러면 처음에 파일을 작성하는 것이 이상해 보입니다. 코드를 게시하지 않았으므로 현재 수행중인 작업을 알 수 없습니다. 그러나 파일을 만들 때 파일을 사용하면 파일을 작성 하기 전에 파일 끝에 File.Create(path)추가해야 .Close()합니다. using파일을 작성한 후 삭제하는 명령문 외에도 이와 같은 함정이 있습니다. 파일을 만들고 삭제하는 방법에 대한 질문에 코드를 게시해야합니다. 그러나 아마도 위에서 언급 한 것과 일치 할 것입니다.
vapcguy

내 코드는 사용 Directory.SetCreationTimeUTC()하지만 파일 탐색기가 열려 있으면 다른 프로세스에서 디렉토리에 액세스한다고 주장하면서 실패합니다. 이 상황을 어떻게 처리해야합니까?
Kyle Delaney

1
@KyleDelaney 폴더가 닫힐 때까지 기다려야한다고 말하고 싶습니다. 몇 초가 지나지 않으면 모든 것이 빠르게 복잡해질 것입니다 (보류중인 작업으로 백그라운드 대기열 유지? 파일 시스템 감시자? 폴링?) 임시 답변에 대한 자세한 내용이 포함 된 질문 게시
Adriano Repetti

29

FileShare를 사용하면 다른 프로세스에서 파일을 열었더라도 파일을 여는 문제가 해결되었습니다.

using (var stream = File.Open(path, FileMode.Open, FileAccess.Write, FileShare.ReadWrite))
{
}

9

이미지를 업로드하는 중에 문제가 발생하여 이미지를 삭제하지 못해 해결책을 찾았습니다. gl hf

//C# .NET
var image = Image.FromFile(filePath);

image.Dispose(); // this removes all resources

//later...

File.Delete(filePath); //now works

2
파일을 삭제하는 경우 이미지 객체를 먼저 삭제해야합니다.
shazia

1
좋아, 나는이 해결책을 찾았다. Image.FromFile 함수에도 문제가있었습니다.
자제

1
@thescion :) np
허드슨

1
이것은 나를 위해 훌륭하게 작동했으며 정확한 문제를 해결했습니다. Tiff 파일의 폴더를 처리하고 바이트 [] 스트림으로 변환하여 서비스로 보낸 다음 Tiff 파일의 폴더를 "처리 된"아카이브 폴더로 옮기고 싶었습니다. Image.FromFile은 Tiff 파일에 잠금을 설정하고 적시에 해제하지 않으므로 Tiff 파일과 포함 폴더를 이동하려고 할 때 잠금이 여전히 "다른 프로세스에서 사용 중"오류가 발생합니다. 그 자리에. Tiff 파일의 바이트를 얻은 직후 .Release를 수행하면이 잠긴 파일 문제가 완전히 해결되었습니다.
Developer63

4

파일 이름이없는 파일 경로로 이동하려면 대상에서 전체 경로를 지정해야합니다.


그리고 파일 이름이없는 것도 아닙니다. 불법 (대상) 파일 이름-내 경우에는 "... \ file" -이 같은 바보 같은 오류를주고 반나절 동안 잘못된 방향으로 당신을 가리킬 것입니다!
Nick Westgate

3

오류는 다른 프로세스가 파일에 액세스하려고 함을 나타냅니다. 글을 쓰려고 시도하는 동안 자신이나 다른 사람이 열었을 수 있습니다. "읽기"또는 "복사"는 일반적으로이를 발생시키지 않지만, 쓰거나 삭제를 호출 할 수 있습니다.

다른 답변에서 언급했듯이 이것을 피할 수있는 몇 가지 기본 사항이 있습니다.

  1. 에서 FileStream운영하는에 배치 usingA를 블록 FileShare.ReadWrite액세스 모드.

    예를 들면 다음과 같습니다.

    using (FileStream stream = File.Open(path, FileMode.Open, FileAccess.Write, FileShare.ReadWrite))
    {
    }

    참고 FileAccess.ReadWrite사용이 불가능합니다 FileMode.Append.

  2. File.SaveAs파일이 사용 중일 때 입력 스트림을 사용 하여이 문제를 겪었습니다 . 필자의 경우 실제로 파일 시스템에 파일을 다시 저장할 필요가 없으므로 그냥 제거했지만 코드와 같이 using문 에서 FileStream을 만들려고했을 수 FileAccess.ReadWrite있습니다. 위.

  3. 더 이상 사용하지 않는 데이터를 다른 파일로 저장하고 이전 파일을 삭제하기 위해 다시 돌아 가면 원래 파일 이름으로 성공적으로 저장된 파일의 이름을 바꾸는 것이 옵션입니다. 사용중인 파일을 테스트하는 방법은

    List<Process> lstProcs = ProcessHandler.WhoIsLocking(file);

    아래 코드 내 라인에 표시되며 Windows 서비스에서 루프로 수행 할 수 있습니다. 파일을 교체 할 때 정기적으로보고 삭제하려는 특정 파일이있는 경우. 항상 같은 파일을 가지고 있지 않은 경우 서비스에서 항상 파일 이름을 확인한 다음 해당 프로세스를 검사하고 그에 따라 프로세스 종료 및 삭제를 수행하도록 텍스트 파일 또는 데이터베이스 테이블을 업데이트 할 수 있습니다. 다음 옵션에서. 물론 프로세스 삭제 및 종료를 수행하려면 주어진 컴퓨터에 대한 관리자 권한이있는 계정 사용자 이름과 비밀번호가 필요합니다.

  4. 파일을 저장하려고 할 때 파일이 사용 중인지 알 수없는 경우 저장하기 전에 Word와 같은 경우 파일과 같이 파일을 사용할 수있는 모든 프로세스를 닫을 수 있습니다.

    로컬 인 경우 다음을 수행 할 수 있습니다.

    ProcessHandler.localProcessKill("winword.exe");

    원격 인 경우 다음을 수행 할 수 있습니다.

    ProcessHandler.remoteProcessKill(computerName, txtUserName, txtPassword, "winword.exe");

    여기서는 txtUserName의 형태이다 DOMAIN\user.

  5. 파일을 잠그는 프로세스 이름을 모른다고 가정 해 봅시다. 그런 다음이 작업을 수행 할 수 있습니다.

    List<Process> lstProcs = new List<Process>();
    lstProcs = ProcessHandler.WhoIsLocking(file);
    
    foreach (Process p in lstProcs)
    {
        if (p.MachineName == ".")
            ProcessHandler.localProcessKill(p.ProcessName);
        else
            ProcessHandler.remoteProcessKill(p.MachineName, txtUserName, txtPassword, p.ProcessName);
    }

    참고 file:의 UNC 경로 여야합니다 \\computer\share\yourdoc.docx(가)의 순서 Process가에 무엇을 컴퓨터 파악하고 p.MachineName유효.

    다음은이 함수가 사용하는 클래스이며에 대한 참조를 추가해야합니다 System.Management. 이 코드는 원래 Eric J가 작성했습니다 .

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Runtime.InteropServices;
    using System.Diagnostics;
    using System.Management;
    
    namespace MyProject
    {
        public static class ProcessHandler
        {
            [StructLayout(LayoutKind.Sequential)]
            struct RM_UNIQUE_PROCESS
            {
                public int dwProcessId;
                public System.Runtime.InteropServices.ComTypes.FILETIME ProcessStartTime;
            }
    
            const int RmRebootReasonNone = 0;
            const int CCH_RM_MAX_APP_NAME = 255;
            const int CCH_RM_MAX_SVC_NAME = 63;
    
            enum RM_APP_TYPE
            {
                RmUnknownApp = 0,
                RmMainWindow = 1,
                RmOtherWindow = 2,
                RmService = 3,
                RmExplorer = 4,
                RmConsole = 5,
                RmCritical = 1000
            }
    
            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
            struct RM_PROCESS_INFO
            {
                public RM_UNIQUE_PROCESS Process;
    
                [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCH_RM_MAX_APP_NAME + 1)]
                public string strAppName;
    
                [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCH_RM_MAX_SVC_NAME + 1)]
                public string strServiceShortName;
    
                public RM_APP_TYPE ApplicationType;
                public uint AppStatus;
                public uint TSSessionId;
                [MarshalAs(UnmanagedType.Bool)]
                public bool bRestartable;
            }
    
            [DllImport("rstrtmgr.dll", CharSet = CharSet.Unicode)]
            static extern int RmRegisterResources(uint pSessionHandle,
                                                UInt32 nFiles,
                                                string[] rgsFilenames,
                                                UInt32 nApplications,
                                                [In] RM_UNIQUE_PROCESS[] rgApplications,
                                                UInt32 nServices,
                                                string[] rgsServiceNames);
    
            [DllImport("rstrtmgr.dll", CharSet = CharSet.Auto)]
            static extern int RmStartSession(out uint pSessionHandle, int dwSessionFlags, string strSessionKey);
    
            [DllImport("rstrtmgr.dll")]
            static extern int RmEndSession(uint pSessionHandle);
    
            [DllImport("rstrtmgr.dll")]
            static extern int RmGetList(uint dwSessionHandle,
                                        out uint pnProcInfoNeeded,
                                        ref uint pnProcInfo,
                                        [In, Out] RM_PROCESS_INFO[] rgAffectedApps,
                                        ref uint lpdwRebootReasons);
    
            /// <summary>
            /// Find out what process(es) have a lock on the specified file.
            /// </summary>
            /// <param name="path">Path of the file.</param>
            /// <returns>Processes locking the file</returns>
            /// <remarks>See also:
            /// http://msdn.microsoft.com/en-us/library/windows/desktop/aa373661(v=vs.85).aspx
            /// http://wyupdate.googlecode.com/svn-history/r401/trunk/frmFilesInUse.cs (no copyright in code at time of viewing)
            /// 
            /// </remarks>
            static public List<Process> WhoIsLocking(string path)
            {
                uint handle;
                string key = Guid.NewGuid().ToString();
                List<Process> processes = new List<Process>();
    
                int res = RmStartSession(out handle, 0, key);
                if (res != 0) throw new Exception("Could not begin restart session.  Unable to determine file locker.");
    
                try
                {
                    const int ERROR_MORE_DATA = 234;
                    uint pnProcInfoNeeded = 0,
                        pnProcInfo = 0,
                        lpdwRebootReasons = RmRebootReasonNone;
    
                    string[] resources = new string[] { path }; // Just checking on one resource.
    
                    res = RmRegisterResources(handle, (uint)resources.Length, resources, 0, null, 0, null);
    
                    if (res != 0) throw new Exception("Could not register resource.");
    
                    //Note: there's a race condition here -- the first call to RmGetList() returns
                    //      the total number of process. However, when we call RmGetList() again to get
                    //      the actual processes this number may have increased.
                    res = RmGetList(handle, out pnProcInfoNeeded, ref pnProcInfo, null, ref lpdwRebootReasons);
    
                    if (res == ERROR_MORE_DATA)
                    {
                        // Create an array to store the process results
                        RM_PROCESS_INFO[] processInfo = new RM_PROCESS_INFO[pnProcInfoNeeded];
                        pnProcInfo = pnProcInfoNeeded;
    
                        // Get the list
                        res = RmGetList(handle, out pnProcInfoNeeded, ref pnProcInfo, processInfo, ref lpdwRebootReasons);
                        if (res == 0)
                        {
                            processes = new List<Process>((int)pnProcInfo);
    
                            // Enumerate all of the results and add them to the 
                            // list to be returned
                            for (int i = 0; i < pnProcInfo; i++)
                            {
                                try
                                {
                                    processes.Add(Process.GetProcessById(processInfo[i].Process.dwProcessId));
                                }
                                // catch the error -- in case the process is no longer running
                                catch (ArgumentException) { }
                            }
                        }
                        else throw new Exception("Could not list processes locking resource.");
                    }
                    else if (res != 0) throw new Exception("Could not list processes locking resource. Failed to get size of result.");
                }
                finally
                {
                    RmEndSession(handle);
                }
    
                return processes;
            }
    
            public static void remoteProcessKill(string computerName, string userName, string pword, string processName)
            {
                var connectoptions = new ConnectionOptions();
                connectoptions.Username = userName;
                connectoptions.Password = pword;
    
                ManagementScope scope = new ManagementScope(@"\\" + computerName + @"\root\cimv2", connectoptions);
    
                // WMI query
                var query = new SelectQuery("select * from Win32_process where name = '" + processName + "'");
    
                using (var searcher = new ManagementObjectSearcher(scope, query))
                {
                    foreach (ManagementObject process in searcher.Get()) 
                    {
                        process.InvokeMethod("Terminate", null);
                        process.Dispose();
                    }
                }            
            }
    
            public static void localProcessKill(string processName)
            {
                foreach (Process p in Process.GetProcessesByName(processName))
                {
                    p.Kill();
                }
            }
    
            [DllImport("kernel32.dll")]
            public static extern bool MoveFileEx(string lpExistingFileName, string lpNewFileName, int dwFlags);
    
            public const int MOVEFILE_DELAY_UNTIL_REBOOT = 0x4;
    
        }
    }

2

이 스레드의 다른 답변에서 지적 했듯이이 오류를 해결하려면 파일이 잠겨있는 위치를 이해하기 위해 코드를주의 깊게 검사해야합니다.

필자의 경우 이동 작업을 수행하기 전에 파일을 전자 메일 첨부 파일로 전송했습니다.

따라서 SMTP 클라이언트가 이메일 전송을 완료 할 때까지 파일이 몇 초 동안 잠겼습니다.

내가 채택한 솔루션은 먼저 파일이동 한 다음 이메일을 보내는 것입니다. 이것은 나를 위해 문제를 해결했습니다.

앞에서 허드슨이 지적한 다른 가능한 해결책은 사용 후 물체를 처리하는 것이 었습니다.

public static SendEmail()
{
           MailMessage mMailMessage = new MailMessage();
           //setup other email stuff

            if (File.Exists(attachmentPath))
            {
                Attachment attachment = new Attachment(attachmentPath);
                mMailMessage.Attachments.Add(attachment);
                attachment.Dispose(); //disposing the Attachment object
            }
} 

파일이 사용 중이면 File.Move()작동하지 않으며 동일한 오류가 발생합니다. 전자 메일에 파일을 추가하면 Attachments.Add()작업 중 사용 중 파일 이 복사 작업이기 때문에 오류가 있다고 생각하지 않습니다 . 어떤 이유로 든 임시 디렉토리에 복사하고 사본을 첨부 한 후 복사 된 파일을 삭제하십시오. 그러나 OP가 파일을 수정하고 사용하려는 경우 이러한 종류의 솔루션 (코드를 표시하지 않고 첨부 부분 만)이 효과가 있다고 생각하지 않습니다. .Dispose()파일은 이전 작업에서 열리지 않는 한 항상 좋은 생각이지만 여기서는 관련이 없습니다.
vapcguy

1

다음과 같은 시나리오에서 동일한 오류가 발생했습니다.

  • 서버에 파일 업로드
  • 그런 다음 이전 파일을 업로드 한 후 제거하십시오.

대부분의 파일은 크기가 작았지만 일부는 크기가 커서 삭제하려고하면 파일에 액세스 할 수 없습니다 . 오류가 발생했습니다.

그러나 찾기가 쉽지는 않았지만 해결책은 "작업이 완료 되기를 기다리는 " 것만 큼 ​​간단했습니다 .

using (var wc = new WebClient())
{
   var tskResult = wc.UploadFileTaskAsync(_address, _fileName);
   tskResult.Wait(); 
}

-1

내 아래 코드는이 문제를 해결하지만 먼저이 문제의 원인을 이해하고 코드를 변경하여 찾을 수있는 솔루션을 시도해야한다고 제안합니다.

이 문제를 해결하는 또 다른 방법을 줄 수는 있지만 더 나은 해결책은 코딩 구조를 확인하고 어떤 일이 발생하는지 분석하는 것입니다. 어떤 해결책을 찾지 못하면 아래 코드를 사용할 수 있습니다

try{
Start:
///Put your file access code here


}catch (Exception ex)
 {
//by anyway you need to handle this error with below code
   if (ex.Message.StartsWith("The process cannot access the file"))
    {
         //Wait for 5 seconds to free that file and then start execution again
         Thread.Sleep(5000);
         goto Start;
    }
 }

1
이 코드의 몇 가지 문제 : 1) 전화 해야하는 경우 GC.*()코드에 다른 문제가있을 수 있습니다. 2) 메시지가 현지화되고 깨지기 쉬우 므로 대신 HRESULT를 사용하십시오. 3) 당신과 함께 자고 싶을 수도 있습니다 Task.Delay()(그리고 많은 경우 10 초가 과도합니다). 4) 종료 조건이 없습니다.이 코드는 계속 중단 될 수 있습니다. 5) 당신은 확실히 goto여기 필요하지 않습니다 . 6) 잡는 Exception것은 일반적으로 나쁜 생각입니다.이 경우에도 ... 6) 다른 일이 발생하면 오류를 삼킨 것입니다.
Adriano Repetti

@ AdrianoRepetti 내 첫 번째 의견은이 코드를 사용하지 말고 다른 솔루션을 찾으려고 노력하십시오. 이것은 마지막 옵션이며 어쨌든이 오류가 발생하면 코드가 중지되지만이 오류 시스템을 처리하는 경우 파일을 확보하기 위해 대기하고 그 후에 시작됩니다 이 코드를 사용하는 동안 GC. *와 다른 문제가 발생하지 않습니다.이 코드로 이미 작업중 인 시스템이 있으므로 게시 한 사람이 도움이 될 수 있습니다.
애쉬

이 코드를 사용하지 않는하기 말하고 싶지만 지금 (때문에 제가 위에서 언급 한 점으로) 나는이 생각하지 않는 게 좋을 작업 자극 시스템을하지만 그냥 내 POV입니다. 동의하지 않습니다!
Adriano Repetti

1)이 서비스를 사용하고 GC를 사용하는 Windows 서비스를 사용했습니다. *이 문제는 없습니다 .2) 예 HRESULT는 코딩 표준 측면에서 더 나은 옵션이 될 수 있습니다 .3) 방금 편집 한 시간에 따라 상황에 따라 다름 5 초까지 4) 어쨌든 오류가 발생한 시스템을 중지하는 대신 리소스를 확보하기 위해 언젠가 시스템을 기다리는 것이 좋습니다 5) 예 예외 처리는 항상 좋은 생각은 아니지만 코드 스 니펫이 작고 알고 있다면 여기서 나는 예외를 처리 할 수 ​​있으며이 솔루션은 당신을위한 옵션입니다.
애쉬

docs.microsoft.com/en-us/archive/blogs/ricom/… 도 참조하십시오 . 내가 사용해야하는 유일한 사례 GC.Collect()는 일부 COM 객체를 다룰 때였습니다.
Adriano Repetti
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.