When is it acceptable to call GC.Collect?

2018-12-31 15:00发布

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 specific cases where it may make sense to force a garbage collection.

One example that springs to mind is a service, that wakes up at intervals, performs some task, and then sleeps for a long time. In this case, it may be a good idea to force a collect to prevent the soon-to-be-idle process from holding on to more memory than needed.

Are there any other cases where it is acceptable to call GC.Collect?

22条回答
若你有天会懂
2楼-- · 2018-12-31 15:37

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%

查看更多
君临天下
3楼-- · 2018-12-31 15:43

One case is when you are trying to unit test code that uses WeakReference.

查看更多
后来的你喜欢了谁
4楼-- · 2018-12-31 15:44

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

查看更多
爱死公子算了
5楼-- · 2018-12-31 15:44

Since there are Small object heap(SOH) and Large object heap(LOH)

We can call GC.Collect() to clear de-reference object in SOP, and move lived object to next generation.

In .net4.5, we can also compact LOH by using largeobjectheapcompactionmode

查看更多
登录 后发表回答