언제 GC.Collect에 전화 할 수 있습니까?


166

일반적인 조언은 GC.Collect코드에서 호출해서는 안되지만 이 규칙의 예외는 무엇입니까?

가비지 수집을 강제하는 것이 합리적 일 수있는 매우 구체적인 몇 가지 사례 만 생각할 수 있습니다.

마음에 떠오르는 한 가지 예는 서비스로, 간격을두고 일어나서 몇 가지 작업을 수행 한 다음 오랫동안 잠 들어 있습니다. 이 경우, 유휴 상태가 될 프로세스가 필요한 것보다 많은 메모리를 보유하지 못하도록 수집을 강제하는 것이 좋습니다.

전화 할 수있는 다른 경우가 GC.Collect있습니까?


답변:


153

중요한 개체 집합, 특히 1 세대와 2 세대에있는 것으로 의심되는 개체 집합이 이제 가비지 수집 대상이되고 작은 성능 저하 측면에서 수집하기에 적절한시기가되었다고 믿을만한 충분한 이유가있는 경우 .

좋은 예는 방금 큰 양식을 닫은 경우입니다. 이제 모든 UI 컨트롤을 가비지 수집 할 수 있으며 양식을 닫을 때 아주 짧은 일시 중지는 사용자에게 눈에 띄지 않을 것입니다.

업데이트 2.7.2018

.NET 4.5으로 -이 GCLatencyMode.LowLatencyGCLatencyMode.SustainedLowLatency. 이 모드 중 하나를 시작하거나 종료 할 때는을 사용하여 전체 GC를 강제 실행하는 것이 좋습니다 GC.Collect(2, GCCollectionMode.Forced).

.NET 4.6부터는 GC.TryStartNoGCRegion(읽기 전용 값을 설정하는 데 사용되는 GCLatencyMode.NoGCRegion) 방법이 있습니다. 이것은 충분한 메모리를 확보하기 위해 전체 차단 가비지 수집을 수행 할 수 있지만 일정 기간 동안 GC를 허용하지 않는다면 전후에 전체 GC를 수행하는 것이 좋습니다.

출처 : Microsoft 엔지니어 Ben Watson : 고성능 .NET 코드 작성 , 2 차 Ed. 2018.

보다:


8
GC.Collect (2)를 호출하는 MS 소스 코드에 따르면 매 850ms마다 괜찮습니다. 믿지 않습니까? 그런 다음 PresentationCore.dll, MS.Internal.MemoryPressure.ProcessAdd ()를 참조하십시오. 현재 GC.Collect (2)를 호출하는 데 850ms 이상 걸리는 이미지 처리 응용 프로그램 (작은 이미지, 실제 메모리 부족은 없음)이 있습니다.
springy76

36
@ springy76 : 한 곳에서 마이크로 소프트에 의해 행해진다고해서 마이크로 소프트 로부터 조언을 해준 사람들에게 좋은 것으로 여겨지는 것은 아닙니다 .
Jon Skeet

4
나는 그 예를 좋아하지 않는다. 양식을 닫은 후에는 무엇을해야합니까? 내가 볼 수있는 좋은 예는 XBox 또는 WindowsPhone에서 게임 레벨을로드 한 후입니다. 이러한 플랫폼에서 GC는 1MB 또는 sth 정도를 할당 한 후에 실행됩니다. 따라서 레벨을로드하는 동안 (스플래쉬 화면이 표시되는 동안) 최대한 많이 할당 한 다음 GC.Collect를 수행하여 게임 중에 수집을 피하도록하십시오.
Piotr Perak

8
@Peri : 폼을 닫은 후 수행하는 요점은 가비지 수집에 적합한 많은 객체 (컨트롤, 표시하는 데이터)를 방금 만든 GC.Collect것입니다. 변화보다 더 낫습니다. 왜 예를 좋아하지 않습니까?
Jon Skeet

6
@SHCJ : GC.Collect()GC가 전체 수집을 수행하도록 요청합니다 . 방금 가비지 컬렉션 대상이 이전에 수명이 긴 물체를 많이했습니다 알고 있다면 그리고 당신은 사용자가 나중에 지금보다 덜 약간의 일시 중지를 통지하는 것입니다 생각, 그 지금 더 나은 생각을 완전히 합리적인 것 같다 나중에 발생하게하는 것보다 컬렉션을 프롬프트 할 시간입니다.
Jon Skeet

50

나는 GC.Collect조잡한 성능 / 프로파일 러 테스트 리그를 작성할 때만 사용 합니다. 즉, 테스트 할 코드 블록이 두 개 이상 있습니다.

GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
TestA(); // may allocate lots of transient objects
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
TestB(); // may allocate lots of transient objects
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
...

그래서 TestA()TestB()가능한 한 유사한 상태로 실행 - 즉 TestB()때문에 단지 망치되지 않습니다 TestA매우 가까운 티핑 포인트를 떠났다.

전형적인 예는 간단한 콘솔 exe ( Main예를 들어 여기에 게시 할 수 있는 방법)인데, 이는 문자열 연결과와의 차이점을 보여줍니다 StringBuilder.

내가 정확한 것을 필요로한다면, 이것은 완전히 독립적 인 두 가지 테스트 일 것입니다.하지만 종종 테스트 중에 GC를 최소화 (또는 정규화)하여 동작에 대한 거친 느낌을 얻으려는 경우에 충분합니다.

생산 코드 중에? 나는 아직 그것을 사용하지 않았다 ;-p


1
그리고 아마도이 경우에도 "WaitForPendingFinalizers"(또는 그 무엇이든)를 추가 할 것입니다. ;-p
Marc Gravell

29

모범 사례는 대부분의 경우 가비지 콜렉션을 강제 실행하지 않는 것입니다. (내가 작업 한 모든 시스템은 가비지 콜렉션을 강제 실행하고, 해결하면 가비지 콜렉션을 강제 실행해야 할 필요성을 제거하고 시스템 속도를 크게 높일 수있는 문제를 강조했습니다.)

있습니다 몇 가지 경우 다음 가비지 컬렉터가하는 메모리 사용에 대해 더 알고있다. 다중 사용자 응용 프로그램이나 한 번에 하나 이상의 요청에 응답하는 서비스에서는 그렇지 않을 수 있습니다.

그러나 일부 배치 유형 처리 에서는 GC보다 더 많은 것을 알고 있습니다. 예를 들어 응용 프로그램을 고려하십시오.

  • 명령 행에 파일 이름 목록이 제공됩니다.
  • 단일 파일을 처리 한 후 결과 파일에 결과를 기록합니다.
  • 파일을 처리하는 동안 파일 처리가 완료 될 때까지 수집 할 수없는 많은 상호 연결된 개체를 만듭니다 (예 : 구문 분석 트리).
  • 처리 한 파일간에 일치 상태를 유지하지 않습니다 .

당신은 할 수 있습니다 각 파일을 처리 한 후에는 전체 가비지 컬렉션을 강제해야 테스트 (주의 후) 케이스를 만들 수.

또 다른 경우는 일부 항목을 처리하기 위해 몇 분마다 깨우는 서비스이며 잠자는 동안 상태를 유지하지 않는 서비스입니다 . 그럼 그냥 잠에 가기 전에 전체 수집을 강제 할 수 있습니다 보람.

컬렉션을 강제로 고려할 수있는 유일한 시간은 최근에 많은 객체가 생성되었고 현재 참조되는 객체가 거의 없다는 것을 알 때입니다.

나는 GC를 스스로 강요하지 않고이 유형의 것에 대한 힌트를 줄 수있을 때 가비지 수집 API를 사용하려고합니다.

" Rico Mariani의 성능 팁 "참조



11

메시지, RPC 요청에 반응하거나 데이터베이스 또는 프로세스를 지속적으로 폴링하는 24/7 또는 24/6 시스템의 경우 메모리 누수를 식별하는 방법이 유용합니다. 이를 위해 처리를 일시적으로 일시 중단 한 다음 전체 가비지 수집을 수행하는 메커니즘을 응용 프로그램에 추가하는 경향이 있습니다. 이렇게하면 시스템이 남아있는 메모리가 합법적으로 오래 사용 된 메모리 (캐시, 구성 등)이거나 '누설 된'(루트가 예상되지 않았지만 실제로는 근본 인 객체) 상태 인 대기 상태가됩니다.

이 메커니즘을 사용하면 활성 처리의 노이즈로 보고서가 흐리게 표시되지 않으므로 메모리 사용량을 훨씬 쉽게 프로파일 링 할 수 있습니다.

모든 가비지를 확보하려면 두 가지 콜렉션을 수행해야합니다.

GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();

첫 번째 컬렉션은 종료자를 가진 모든 객체를 마무리하지만 실제로는 이러한 객체를 가비지 수집하지 않습니다. 두 번째 GC는 이러한 최종 객체를 가비지 수집합니다.


지금은 두 곳에서 2 패스 수집을 보았지만 GC.WaitForPendingFinalizers 에 대한 MSDN 설명서의 내용을 읽은 후 다음 과 같이 말합니다. "계속하기 전에 모든 종료자가 완료 될 때까지 기다리십시오. 아래의 작업자 루프는 종료 자와 동시에 실행될 수 있습니다.이 호출을 통해 작업자 루프는 모든 종료자가 호출 된 후에 만 ​​실행됩니다. " 나는 단지 터치 편집증입니다. 두 번의 통과를위한 결정적인 소스를 알고 있습니까?
jerhewet

1
@jerhewet : 두 컬렉션이 필요한 이유를 이해하는 열쇠는 finalizer를 사용하여 객체에 어떤 일이 발생하는지 이해하는 것입니다. 불행하게도, 난 당신이 요구하는지 정확히 무엇을 가지고 있지만,의 읽기가없는 이 문서SO에이 질문을 .
Paul Ruane 2016 년

10

가비지 수집기에서 제공하지 않는 앱의 특성에 대해 알고있는 경우 GC.Collect ()를 호출 할 수 있습니다. 저자로서 이것이 가능성이 높다고 생각하고 싶어합니다. 그러나 진실은 GC가 꽤 잘 작성되고 테스트 된 전문가 시스템에 해당하며, 저수준 코드 경로에 대해 알지 못하는 경우는 거의 없습니다.

추가 정보가있는 위치를 생각할 수있는 가장 좋은 예는 유휴 기간과 매우 바쁜 기간 사이를 순환하는 앱입니다. 사용량이 많은 기간 동안 가능한 최고의 성능을 원하므로 유휴 시간을 사용하여 정리를 수행하려고합니다.

그러나 대부분의 경우 GC는 어쨌든 이것을 할만 큼 똑똑합니다.


8

메모리 조각화 솔루션으로. 많은 데이터를 메모리 스트림에 쓰는 동안 (네트워크 스트림에서 읽음) 메모리 예외가 발생했습니다. 데이터는 8K 청크로 작성되었습니다. 128M에 도달 한 후 사용 가능한 메모리가 많지만 예외가 발생했습니다 (그러나 조각화 됨). GC.Collect ()를 호출하면 문제가 해결되었습니다. 수정 후 1G 이상을 처리 할 수있었습니다.


7

Rico Mariani의이 기사를 살펴보십시오. 그는 GC.Collect를 호출 할 때 두 가지 규칙을 제공합니다 (규칙 1은 "안함").

GC.Collect ()를 호출 할 때


3
이미 거기에 있었다. 나는 당신이해서는 안되는 일을하는 변명을 찾으려고하지 않지만 수용 가능한 특정 사례가 있는지 알고 싶습니다.
Brian Rasmussen

5

GC.Collect () 호출이 거의 필요한 경우는 Interop을 통해 Microsoft Office를 자동화 할 때입니다. Office 용 COM 개체는 자동으로 릴리스하는 것을 좋아하지 않으므로 Office 제품 인스턴스가 매우 많은 양의 메모리를 차지할 수 있습니다. 이것이 문제인지 또는 의도적인지 확실하지 않습니다. 인터넷 주위 에이 주제에 관한 많은 게시물이 있으므로 너무 자세하게 다루지 않습니다.

Interop를 사용하여 프로그래밍 할 때는 일반적으로 Marshal.ReleseComObject ()를 사용하지만 모든 단일 COM 개체를 수동으로 해제해야합니다. 또한 가비지 콜렉션을 수동으로 호출하면 "정리"하는 데 도움이됩니다. Interop 개체를 다룰 때 다음 코드를 호출하면 상당히 도움이 될 것 같습니다.

GC.Collect()
GC.WaitForPendingFinalizers()
GC.Collect()

개인적으로 ReleaseComObject와 수동으로 가비지 수집을 함께 사용하면 Office 제품, 특히 Excel의 메모리 사용량이 크게 줄어 듭니다.


그렇습니다 .com 객체를 통해 작동하는 .net 액세스 엑셀로 그 문제에 부딪 쳤습니다. GC 작업이 제한되어 있기 때문에 DEBUG 모드에서는이 기능이 제대로 작동하지 않습니다. RELEASE 모드에서만 의도 한대로 작동합니다. 관련 링크 : stackoverflow.com/questions/17130382/…
Blechdose

5

배열 및 목록에서 성능 테스트를 수행했습니다.

private static int count = 100000000;
private static List<int> GetSomeNumbers_List_int()
{
    var lstNumbers = new List<int>();
    for(var i = 1; i <= count; i++)
    {
        lstNumbers.Add(i);
    }
    return lstNumbers;
}
private static int[] GetSomeNumbers_Array()
{
    var lstNumbers = new int[count];
    for (var i = 1; i <= count; i++)
    {
        lstNumbers[i-1] = i + 1;
    }
    return lstNumbers;
}
private static int[] GetSomeNumbers_Enumerable_Range()
{
    return  Enumerable.Range(1, count).ToArray();
}

static void performance_100_Million()
{
    var sw = new Stopwatch();

    sw.Start();
    var numbers1 = GetSomeNumbers_List_int();
    sw.Stop();
    //numbers1 = null;
    //GC.Collect();
    Console.WriteLine(String.Format("\"List<int>\" took {0} milliseconds", sw.ElapsedMilliseconds));

    sw.Reset();
    sw.Start();
    var numbers2 = GetSomeNumbers_Array();
    sw.Stop();
    //numbers2 = null;
    //GC.Collect();
    Console.WriteLine(String.Format("\"int[]\" took {0} milliseconds", sw.ElapsedMilliseconds));

    sw.Reset();
    sw.Start();
//getting System.OutOfMemoryException in GetSomeNumbers_Enumerable_Range method
    var numbers3 = GetSomeNumbers_Enumerable_Range();
    sw.Stop();
    //numbers3 = null;
    //GC.Collect();

    Console.WriteLine(String.Format("\"int[]\" Enumerable.Range took {0} milliseconds", sw.ElapsedMilliseconds));
}

내가 가지고 OutOfMemoryException있는 유일한 해결 방법으로 메모리 할당을 해제하는 것입니다 GetSomeNumbers_Enumerable_Range의 방법 :

numbers = null;
GC.Collect();

왜 투표를하지 않습니까? 내 대답은 언제 GC에 전화해야하는지 보여주는 예입니다. 더 나은 제안이 있으십니까?
Daniel B

4

귀하의 예에서 GC.Collect를 호출하는 것은 문제가 아니라 디자인 문제가 있다고 생각합니다.

일정한 간격으로 (설정된 시간) 깨우려면 프로그램을 한 번만 실행하고 (작업을 한 번 수행) 종료해야합니다. 그런 다음 프로그램을 예약 된 간격으로 실행되도록 예약 된 작업으로 설정합니다.

이 방법을 사용하면 GC.Collect를을 (당신이해야하는 전화와 우려 자신을 필요 없어 거의 어느 경우 수행 할 필요가 없습니다).

그러나 Rico Mariani는이 주제에 대한 훌륭한 블로그 게시물을 가지고 있으며 여기에서 찾을 수 있습니다.

http://blogs.msdn.com/ricom/archive/2004/11/29/271829.aspx


3

GC.Collect ()를 호출하는 유용한 장소 중 하나는 메모리 누수가 발생하지 않는지 확인하려는 경우 (예 : WeakReferences 또는 ConditionalWeakTable, 동적으로 생성 된 코드 등으로 작업하는 경우) 단위 테스트입니다.

예를 들어 다음과 같은 몇 가지 테스트가 있습니다.

WeakReference w = CodeThatShouldNotMemoryLeak();
Assert.IsTrue(w.IsAlive);
GC.Collect();
GC.WaitForPendingFinalizers();
Assert.IsFalse(w.IsAlive);

WeakReferences를 사용하는 것이 그 자체로 문제라고 주장 할 수는 있지만 그러한 동작에 의존하는 시스템을 만드는 경우 GC.Collect ()를 호출하는 것이 그러한 코드를 확인하는 좋은 방법 인 것 같습니다.




2
using(var stream = new MemoryStream())
{
   bitmap.Save(stream, ImageFormat.Png);
   techObject.Last().Image = Image.FromStream(stream);
   bitmap.Dispose();

   // Without this code, I had an OutOfMemory exception.
   GC.Collect();
   GC.WaitForPendingFinalizers();
   //
}

2

미안보다 안전한 것이 더 좋은 상황이 있습니다.

한 가지 상황이 있습니다.

저자 수있다 단독 (이것은 필요가있는 경우가 있기 때문에) IL의 재기록을 이용하여 C #에서 DLL을.

예를 들어, DLL은 클래스 수준에서 바이트 배열을 생성한다고 가정합니다. 내 보낸 많은 함수에 액세스해야하기 때문입니다. DLL이 언로드되면 어떻게됩니까? 이 시점에서 가비지 수집기가 자동으로 호출됩니까? 모르겠지만 관리되지 않는 DLL이기 때문에 GC가 호출되지 않을 수도 있습니다. 그리고 그것이 불려지지 않으면 큰 문제가 될 것입니다. DLL이 언로드되면 가비지 수집기가됩니다. 그러면 가비지 수집을 담당하는 사람은 누구이며 어떻게 수행합니까? C #의 가비지 수집기를 사용하는 것이 좋습니다. 클래스 레벨 변수가 널로 설정되고 가비지 콜렉터가 호출되는 정리 함수 (DLL 클라이언트에 사용 가능)가 있어야합니다.

죄송합니다보다 더 안전.


2

나는 아직도 이것에 대해 확신이 없다. 저는 7 년 동안 Application Server에서 일하고 있습니다. 우리의 더 큰 설치는 24GB 램을 사용합니다. GC.Collect ()에 대한 높은 멀티 스레드 및 모든 호출은 실제로 끔찍한 성능 문제를 일으켰습니다.

많은 타사 구성 요소가 현재이 작업을 영리하다고 생각했을 때 GC.Collect ()를 사용했습니다. 따라서 간단한 Excel 보고서가 분당 여러 번 모든 스레드에 대해 App Server를 차단했습니다.

GC.Collect () 호출을 제거하기 위해 모든 타사 구성 요소를 리팩터링해야 했으며이 작업을 수행 한 후에는 모두 정상적으로 작동했습니다.

그러나 Win32에서도 서버를 실행하고 있으며 OutOfMemoryException을 얻은 후 GC.Collect ()를 많이 사용하기 시작했습니다.

그러나 32 비트에서 OOM을 얻었을 때 GC.Collect ()를 호출하지 않고 동일한 작업을 다시 실행하려고하면 종종 잘 작동했기 때문에 이것에 대해 확신이 없습니다.

내가 궁금한 것 중 하나는 OOM 예외 자체입니다 ... .Net Framework를 작성하고 메모리 블록을 할당 할 수 없으면 GC.Collect (), 조각 모음 메모리 (??)를 사용하고 다시 시도하십시오. , 여전히 사용 가능한 메모리 블록을 찾을 수 없으면 OOM-Exception이 발생합니다.

또는 적어도 GC.Collect의 성능 문제로 인해이 동작을 구성 가능한 옵션으로 만드십시오.

이제 문제를 "해결"하기 위해 내 앱에 이와 같은 코드가 많이 있습니다.

public static TResult ExecuteOOMAware<T1, T2, TResult>(Func<T1,T2 ,TResult> func, T1 a1, T2 a2)
{

    int oomCounter = 0;
    int maxOOMRetries = 10;
    do
    {
        try
        {
            return func(a1, a2);
        }
        catch (OutOfMemoryException)
        {
            oomCounter++;
            if (maxOOMRetries > 10)
            {
                throw;
            }
            else
            {
                Log.Info("OutOfMemory-Exception caught, Trying to fix. Counter: " + oomCounter.ToString());
                System.Threading.Thread.Sleep(TimeSpan.FromSeconds(oomCounter * 10));
                GC.Collect();
            }
        }
    } while (oomCounter < maxOOMRetries);

    // never gets hitted.
    return default(TResult);
}

(ORM 캐싱 서비스를 실행하고 있기 때문에 Thread.Sleep () 비헤이비어는 실제로 앱에 적합한 동작입니다. RAM이 미리 정의 된 값을 초과하면 서비스가 캐시 된 모든 객체를 해제하는 데 시간이 걸립니다. 처음 몇 초 동안 OOM이 발생할 때마다 대기 시간이 늘어났습니다.)


컴포넌트는를 호출해서는 안됩니다 GC.Collect. 응용 프로그램 전체에 영향을 미치므로 응용 프로그램 만 적용해야합니다.
코드 InChaos 2016 년

If i would have written the .Net Framework, and i can't alloc a memory block, i would use GC.Collect(),-나는 그들이 이미 이것을하고 있다고 생각합니다-내부 GC 트리거 중 하나가 메모리 할당에 실패한다는 표시를 보았습니다.
G. Stoynev

2

GC.Collect ()는 매우 비싸므로 사용하지 마십시오. 예를 들면 다음과 같습니다.

        public void ClearFrame(ulong timeStamp)
    {
        if (RecordSet.Count <= 0) return;
        if (Limit == false)
        {
            var seconds = (timeStamp - RecordSet[0].TimeStamp)/1000;
            if (seconds <= _preFramesTime) return;
            Limit = true;
            do
            {
                RecordSet.Remove(RecordSet[0]);
            } while (((timeStamp - RecordSet[0].TimeStamp) / 1000) > _preFramesTime);
        }
        else
        {
            RecordSet.Remove(RecordSet[0]);

        }
        GC.Collect(); // AVOID
    }

테스트 결과 : CPU 사용량 12 %

이것으로 변경할 때 :

        public void ClearFrame(ulong timeStamp)
    {
        if (RecordSet.Count <= 0) return;
        if (Limit == false)
        {
            var seconds = (timeStamp - RecordSet[0].TimeStamp)/1000;
            if (seconds <= _preFramesTime) return;
            Limit = true;
            do
            {
                RecordSet[0].Dispose(); //  Bitmap destroyed!
                RecordSet.Remove(RecordSet[0]);
            } while (((timeStamp - RecordSet[0].TimeStamp) / 1000) > _preFramesTime);
        }
        else
        {
            RecordSet[0].Dispose(); //  Bitmap destroyed!
            RecordSet.Remove(RecordSet[0]);

        }
        //GC.Collect();
    }

테스트 결과 : CPU 사용량 2-3 %


1

또 다른 이유는 USB COM 포트에 SerialPort가 열려 있고 USB 장치가 분리되어 있기 때문입니다. SerialPort가 열렸 기 때문에 자원은 시스템 레지스트리에서 이전에 연결된 포트에 대한 참조를 보유합니다. 그러면 시스템의 레지스트리에 오래된 데이터가 포함 되므로 사용 가능한 포트 목록이 잘못됩니다. 따라서 포트를 닫아야합니다.

포트에서 SerialPort.Close ()를 호출하면 개체에서 Dispose ()가 호출되지만 가비지 수집이 실제로 실행될 때까지 메모리에 남아 있으므로 가비지 수집기가 리소스를 해제하기로 결정할 때까지 레지스트리가 오래 유지됩니다.

에서 https://stackoverflow.com/a/58810699/8685342 :

try
{
    if (port != null)
        port.Close(); //this will throw an exception if the port was unplugged
}
catch (Exception ex) //of type 'System.IO.IOException'
{
    System.GC.Collect();
    System.GC.WaitForPendingFinalizers();
}

port = null;

0

이것은 질문과 관련이 없지만 .NET (XSLCompiledTranform)의 XSLT 변환의 경우 선택의 여지가 없습니다. 또 다른 후보는 MSHTML 컨트롤입니다.



0

GC를 호출하는 좋은 이유 중 하나는 Raspberry PI (모노로 실행)와 같이 메모리가 적은 소형 ARM 컴퓨터에 있습니다. 할당되지 않은 메모리 조각이 너무 많은 시스템 RAM을 사용하면 Linux OS가 불안정해질 수 있습니다. 메모리 오버플로 문제를 해결하기 위해 매초 GC를 호출 해야하는 응용 프로그램이 있습니다 (!).

또 다른 좋은 해결책은 더 이상 필요하지 않은 객체를 폐기하는 것입니다. 불행히도 이것은 많은 경우에 그렇게 쉬운 일이 아닙니다.


0

작은 개체 힙 (SOH)과 큰 개체 힙 (LOH)이 있으므로

GC.Collect ()를 호출하여 SOP에서 역 참조 객체를 지우고 활성 객체를 다음 세대로 옮길 수 있습니다.

.net4.5, 우리는 사용하여 컴팩트 LOH 수 largeobjectheapcompactionmode을


0

많은 새로운 System.Drawing.Bitmap객체를 생성하는 경우 가비지 콜렉터가 지우지 않습니다. 결국 GDI +는 메모리가 부족하다고 생각하고 "매개 변수가 유효하지 않습니다"예외를 발생시킵니다. GC.Collect()너무 자주는 아니지만 자주 전화 하면이 문제가 해결되는 것 같습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.