When is it acceptable to call GC.Collect?

前端 未结 24 2150
挽巷
挽巷 2020-11-22 08:54

The general advise is that you should not call GC.Collect from your code, but what are the exceptions to this rule?

I can only think of a few very speci

相关标签:
24条回答
  • 2020-11-22 09:22

    Have a look at this article by Rico Mariani. He gives two rules when to call GC.Collect (rule 1 is: "Don't"):

    When to call GC.Collect()

    0 讨论(0)
  • 2020-11-22 09:22

    In your example, I think that calling GC.Collect isn't the issue, but rather there is a design issue.

    If you are going to wake up at intervals, (set times) then your program should be crafted for a single execution (perform the task once) and then terminate. Then, you set the program up as a scheduled task to run at the scheduled intervals.

    This way, you don't have to concern yourself with calling GC.Collect, (which you should rarely if ever, have to do).

    That being said, Rico Mariani has a great blog post on this subject, which can be found here:

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

    0 讨论(0)
  • 2020-11-22 09:23

    Another reason is when you have a SerialPort opened on a USB COM port, and then the USB device is unplugged. Because the SerialPort was opened, the resource holds a reference to the previously connected port in the system's registry. The system's registry will then contain stale data, so the list of available ports will be wrong. Therefore the port must be closed.

    Calling SerialPort.Close() on the port calls Dispose() on the object, but it remains in memory until garbage collection actually runs, causing the registry to remain stale until the garbage collector decides to release the resource.

    From 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 讨论(0)
  • 2020-11-22 09:24

    You should try to avoid using GC.Collect() since its very expensive. Here is an example:

            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
        }
    

    TEST RESULT: CPU USAGE 12%

    When you change to this:

            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();
        }
    

    TEST RESULT: CPU USAGE 2-3%

    0 讨论(0)
  • 2020-11-22 09:26

    This isn't that relevant to the question, but for XSLT transforms in .NET (XSLCompiledTranform) then you might have no choice. Another candidate is the MSHTML control.

    0 讨论(0)
  • 2020-11-22 09:29

    In large 24/7 or 24/6 systems -- systems that react to messages, RPC requests or that poll a database or process continuously -- it is useful to have a way to identify memory leaks. For this, I tend to add a mechanism to the application to temporarily suspend any processing and then perform full garbage collection. This puts the system into a quiescent state where the memory remaining is either legitimately long lived memory (caches, configuration, &c.) or else is 'leaked' (objects that are not expected or desired to be rooted but actually are).

    Having this mechanism makes it a lot easier to profile memory usage as the reports will not be clouded with noise from active processing.

    To be sure you get all of the garbage, you need to perform two collections:

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

    As the first collection will cause any objects with finalizers to be finalized (but not actually garbage collect these objects). The second GC will garbage collect these finalized objects.

    0 讨论(0)
提交回复
热议问题