2011-01-28 1 views
1

나는 런타임에서 그리고 플랫폼 비트 - 네스 (language-native)를 기반으로 자원에서 추출한 .NET 프로젝트를 가지고있다. LoadLibrary, GetProcAddress 및 FreeLibrary를 사용하여 라이브러리의로드 및 관리를 관리 코드에서 관리합니다..NET SafeHandle 클래스를 사용하고 그 안에 핸들을 결정적으로 해제 할 수 있습니까?

기본 라이브러리로 작업을 마친 후 삭제하고 싶습니다. 여기로 현재 구현 된 워크 플로우를 보여주는 몇 의사 코드의 : 유형을 IntPtr의 변수를 사용할 때 잘 작동

internal class MyClass() 
{  
    string nativeLibraryPath = "C:\my\path\to\extracted\library.dll"; 
    IntPtr nativeLibraryHandle = IntPtr.Zero; 

    public void Load() 
    { 
     nativeLibraryHandle = NativeMethods.LoadLibrary(nativeLibraryPath); 
    } 

    public void ExecuteFunction() 
    { 
     IntPtr functionPointer = NativeMethods.GetProcAddress(nativeLibraryHandle, "MyFunctionName"); 
     // assume MyManagedDelegate is defined as the correct delegate type. 
     MyManagedDelegate managedFunction = Marshal.GetDelegateForFunctionPointer(functionPointer, typeof(MyManagedDelegate)) as MyManagedDelegate; 
     managedFunction("foo", "bar"); 
    } 

    public void Unload() 
    { 
     NativeMethods.FreeLibrary(nativeLibraryHandle); 
     File.Delete(nativeLibraryPath); 
    } 
} 

. 현명한 지혜 (모범 사례?)는 SafeHandle이 더 나은 접근 방식 일 수 있음을 나타냅니다. 그러나, SafeHandle을 사용할 때 ReleaseHandle() 메서드는 결정적으로 호출되지 않는다는 것을 이해합니다. 즉, SafeHandle에서만 Close() 또는 Dispose() 메서드를 호출하면 은 가비지 수집 클래스로 표시됩니다. 객체가 수집 될 때까지 ReleaseHandle을 호출하지 않습니다. 네이티브 코드 .DLL이 언로드 될 때까지 삭제할 수 없기 때문에이 문제가 발생합니다. ReleaseHandle에서 FreeLibrary를 호출하면 어떻게 GC.Collect()를 호출하는 것과 같은 해커리에 의지하지 않고 라이브러리가 해제 될 때까지 결정적으로 기다릴 수 있습니까?

수정 실제 코드가 어떻게 구성되어 있는지 더 대표적으로 예를 업데이트했습니다. 이 예제에 게시 된 코드는 완전하지 않습니다. 필자는 프로덕션 코드에서 필요한 오류 검사 및 예외 처리를 포함합니다.

답변

2

아니, 그건 정확하지 않습니다. SafeHandle은 코드에서 잊어 버렸을 때 핸들을 해제합니다. 인 경우에만이 최종 결정자 스레드에서 실행되는 코드 인 비 결정적으로 발생합니다. Dispose()를 호출하는 것은 매우 결정적입니다.

작성한 코드는 이 아니며이 아니므로 예외가 발생하면 폭탄 처리시 모듈 핸들이 영구적으로 누출됩니다. finally 블록을 사용하여 핸들이 해제되었는지 확인해야합니다. 어느 것이 꽤 괜찮습니까? 여기서는 SafeHandle이 필요하지 않습니다. 왜냐하면 핸들을 로컬 변수로 유지하고 항상 결정 론적으로 해제 할 수 있기 때문입니다.

+0

예에서 제공하는 의사 코드가 안전하지 않다는 것을 알고 있지만이 질문을 통해 다른 사람이 누릴 수있는 이점을 지적 해 주셔서 감사합니다. 로드 및 언로드가 클래스의 다른 메서드에 의해 처리되므로 (즉 핸들이 단일 메서드의 로컬 변수가 아니라) 제공된 예제 코드가 실제 워크 플로에 잘못된 인상을줍니다. . 그게 당신의 대답을 바꾸나요? – JimEvans

+0

물론, 당신은 내 대답을 쓸어 버렸다. 새 버전에는 SafeHandle 또는 소멸자가 필요하며 여기서 확실히 SafeHandle을 사용하십시오. IDisposable을 구현해야합니다. –

2

틀렸어.
Close()으로 전화하면 핸들이 해제됩니다. 그 참조 횟수가 0 인 경우

그러나, 그것은 단지 (이 핸들에 의해 유지되고, GC가 REF-수를 사용하지 않습니다) 핸들을 닫습니다

관련 문제