내용 보기
작성자
관리자 (IP : 172.17.0.1)
날짜
2022-03-22 09:20
제목
[C#] 다시 한번 기초 다지기! - GC의 Collect, WaitForFullGCComplete, finalize 메서드(소멸자)
Collect, WaitForFullGCComplete, finalize 메서드(소멸자)에 대해 설명하겠다. // 가비지 컬렉터를 작동시킨다
System.GC.Collect(0, GCCollectionMode.Forced);
System.GC.WaitForFullGCComplete(); GC.Collect() 메서드역할
+ GCCollectionMode의 종류 - 언제 동작할건지
// 강제로 가비지 컬렉션을 작동
// 0세대에서 0세대까지만 가비지 수집을 즉시 실행한다.
System.GC.Collect(0, GCCollectionMode.Forced);
//System.GC.WaitForFullGCComplete(); //0세대부터 2세대까지 GC실행시키기에 최적의 시간인지 결정한 뒤 최적의 시간에 GC실행
System.GC.Collect(2, GCCollectionMode.Optimized);
GC.WaitForFullGCComplete() 메서드역할
//WaitForFullGCComplete 메소드 정의 형식
public static GCNotificationStatus WaitForFullGCComplete() // Check for a notification of a completed collection.
GCNotificationStatus s = GC.WaitForFullGCComplete();
if (s == GCNotificationStatus.Succeeded)
{
Console.WriteLine("GC Notifiction raised.");
OnFullGCCompleteEndNotify();
}
else if (s == GCNotificationStatus.Canceled)
{
Console.WriteLine("GC Notification cancelled.");
break;
}
else
{
// Could be a time out.
Console.WriteLine("GC Notification not applicable.");
break;
} GC의 소멸자 메서드Finalize() - 소멸자정의 class UnmanagedMemoryManager
{
~UnmanagedMemoryManager()
{
/*관리되지 않는 리소스를 정리*/
}
} 위의 소멸자코드는 아래의 코드로 대체된다 protected override void Finalize()
{
try { /*관리되지 않는 리소스를 정리*/ }
finally { base.Finalize(); }
}
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace Destructor_sample
{
class Program
{
static void Main(string[] args)
{
while(true)
{
UnmanagedMemoryManager m = new UnmanagedMemoryManager();
m = null;
GC.Collect(); // GC를 강제로 수행
//현재 프로세스가 사용하는 메모리 크기 출력
Console.WriteLine(Process.GetCurrentProcess().PrivateMemorySize64);
}
}
}
class UnmanagedMemoryManager
{
IntPtr pBuffer;
public UnmanagedMemoryManager()
{
//AllocCoTaskMem메서드는 비관리 메모리를 할당한다.
pBuffer = Marshal.AllocCoTaskMem(4096 * 1024);//의도적으로 4MB 할당
}
}
}
결과: OutOfMemoryException 에러 발생 설명: UnmanagedMemoryManager 클래스는 생성자에서 4MB 크기의 비관리 메모리를 할당한다. using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace Destructor_sample
{
class Program
{
static void Main(string[] args)
{
while(true)
{
//Dispose()메소드를 자동 실행
using (UnmanagedMemoryManager m = new UnmanagedMemoryManager())
{
}
//현재 프로세스가 사용하는 메모리 크기 출력
Console.WriteLine(Process.GetCurrentProcess().PrivateMemorySize64);
}
}
}
class UnmanagedMemoryManager : IDisposable
{
IntPtr pBuffer;
public UnmanagedMemoryManager()
{
//AllocCoTaskMem메서드는 비관리 메모리를 할당한다.
pBuffer = Marshal.AllocCoTaskMem(4096 * 1024);//의도적으로 4MB 할당
}
//Dispose()메소드 구현
public void Dispose()
{
Marshal.FreeCoTaskMem(pBuffer);
}
}
}
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace Destructor_sample
{
class Program
{
static void Main(string[] args)
{
while(true)
{
//Dispose()메소드를 자동 실행
UnmanagedMemoryManager m = new UnmanagedMemoryManager();
m = null;
//GC로 인해 소멸자가 호출되므로 비관리 메모리도 해제됨.
//GC.Collect()를 명시적으로 부르지 않아도 메모리가 부족하면
//GC는 자동적으로 실행됨
GC.Collect();
//현재 프로세스가 사용하는 메모리 크기 출력
Console.WriteLine(Process.GetCurrentProcess().PrivateMemorySize64);
}
}
}
class UnmanagedMemoryManager : IDisposable
{
IntPtr pBuffer;
bool _disposed;
public UnmanagedMemoryManager()
{
//AllocCoTaskMem메서드는 비관리 메모리를 할당한다.
pBuffer = Marshal.AllocCoTaskMem(4096 * 1024);//의도적으로 4MB 할당
}
//Dispose()메소드 구현
public void Dispose()
{
if (_disposed == false)
{
Marshal.FreeCoTaskMem(pBuffer);
_disposed = true;
}
}
~UnmanagedMemoryManager()//소멸자: 가비지 수집이 되면 호출된다.
{
Dispose();
}
}
}
소멸자는 GC가 동작한다면 호출되는 것이 보장된다. using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace Destructor_sample
{
class Program
{
static void Main(string[] args)
{
while(true)
{
//Dispose()메소드를 자동 실행
using (UnmanagedMemoryManager m = new UnmanagedMemoryManager())
{
}
//GC.Collect();//GC로 인해 소멸자가 호출되므로 비관리 메모리도 해제됨.
//현재 프로세스가 사용하는 메모리 크기 출력
Console.WriteLine(Process.GetCurrentProcess().PrivateMemorySize64);
}
}
}
class UnmanagedMemoryManager : IDisposable
{
IntPtr pBuffer;
bool _disposed;
public UnmanagedMemoryManager()
{
//AllocCoTaskMem메서드는 비관리 메모리를 할당한다.
pBuffer = Marshal.AllocCoTaskMem(4096 * 1024);//의도적으로 4MB 할당
}
//Dispose()메소드 구현
public void Dispose(bool disposing)
{
//Dispose()메소드를 명시적으로 호출하든
//소멸자를 통해 호출하든 공통적으로 동작
if (_disposed == false)
{
Marshal.FreeCoTaskMem(pBuffer);
_disposed = true;
}
//Dispose()메소드를 명시적으로 호출한 경우
if(disposing == false)
{
//disposing이 false인 경우란 명시적으로 Dispose()를 호출한 경우다.
//따라서 종료 큐에서 자신을 제거해 GC의 부담을 줄인다.
GC.SuppressFinalize(this);
}
}
public void Dispose()
{
Dispose(false);
}
~UnmanagedMemoryManager()//소멸자: 가비지 수집이 되면 호출된다.
{
Dispose(true);
}
}
}
위의 예제에서 new로 객체를 생성하면 종료 큐에 객체가 추가된다. |
출처1
https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=sam_sist&logNo=221002701762
출처2