-
Notifications
You must be signed in to change notification settings - Fork 1
Day 10 GC and IDisposables
Kobi Hari edited this page Nov 12, 2020
·
1 revision
Fun with Resources | Some experiments with the GC and some fun things to do with disposables |
- We talked about 4 memory areas
- Stack (per thread)
- Heap
- Static
- Code
- We talked about the Reachable Object Graph
- Starts from the Stacks and Static
- Walks through object references
- Objects that are not reachable are marked for collection
- We talked about when the GC Runs
- Memory Allocation Failed
- Application Shutdown
- Manually running GC
- We said that the GC Does the following:
- Calculates the reachable object graph
- Releases unreachable objects
- Runs Defragmantation of memory
- Updates references to objects that moved
- GC is blocking, When the GC runs, all threads stop
- We talked about GC Generations
- The more times an object "survives" GC, the higher it's generation is, and it is assumed the it is more likely to survive the next GC
- We can test generation using
GC.GetGeneration
- We can use
GC.GetTotalMemory
to get the size of the heap
- We talked about Unmanaged Resources
- The GC only frees the managed memory
- There are other resources that are not managed (File streams, connections, and so on)
- In order to handle unmanaged resources, you can write a destructor (~ method) which will be executed by the GC
- Rules for writing destructors
- You cannot manually call a destructor, only the GC may call it
- You cannot pass parameters to the destructor and it has no return value (not even void)
- You cannot overload desctructors
- You cannot restrict access (public, protected, and so on)
- You cannot define destructor to Value types, since they reside on the stack and are therefore not desctructed
- Destcrutor of subclass runs before the destructor of the base class (opposite to constructor)
- You should not touch any external objects (managed) when inside a finalizer
- We talked a little about GC Settings and Heuristics
- The CLR supports 2 types of garbase collectors
- Server GC - Mostly suited for 4 processors
- Workstation GC - Mostly suited for single processor, or 2 processors
- Concurrent GC
- Starting from .net 4.5, server garbage collection is concurrent.
- Starting from .net 4.6.2, you can also configure if there is affinity between each processor and the heap, the heap count.
- Configuring the GC
- You can set the GC type (server or workstation)
- you can enable and disable concurrent GC (for server GC)
- you can configure heap processor affinity and the heap count (for server GC)
- References:
- We talked about Motivation:
- We have no control over when the destructor is called
- The destructor slows down the GC which blocks the application
- The order destructors are called is unpredictable
-
IDisposable
is an interface for voluntary destruction - Usually, the destructor calls
Dispose
to make sure the object is disposed when it is cleaned - We Created an object that frees resources both on destructor and on Dispose
- We observed a problem: we have freed the resources twice
- We used
GC.SuprressFinalize(this)
on Dispose - this way the destructor will not run - Another option is to call Dispose from the Destructor and make sure dispose only really runs once.
- We saw how to handle internal disposable objects
- When we are disposing our object, we need to also dispose the internal object
- But if the GC initiated the dispose, it is possible that the objects have already been destructed, so we cannot call any method on them
- So we add a boolean parameter to dispose so that disposing while GC is done non recursively
- Keep a boolean
isDisposed
to make sure we are not disposed twice - Throw
ObjectDisposedException
when running method after disposal - We talked about The
using
statement- Calls the
Dispose
method automatically when leaving the block - Uses variable scope to prevent access to disposed object
- Any termination of the block (using
return
,throw
,continue
,break
are all different ways to exit block) will cause Dispose to run
- Calls the
- BaseDisposable
- Support IsDisposed
- throws
ObjectDisposedException
- supports destructor disposing
- supports isDisposing parameter
- Supports
Disposing
event (INotifyDisposable interface
)
- We created a Disposable.Call method that converts an action into disposable that calls the action on dispose
- We Implemented a "DisposedBy" method that disposes one disposable when the opther disposable disposes
- We create some Other Examples
- Cool Examples
- Create a disposable counter
- Writing to the console with specific color
- We used disposables to Create AsyncMutex
- The mutex itself is a factory of "premission to access critical code"
- The factory method returns a
Task<IDisposable>
where theIDisposable
is a token that grants permission to access the critical code and disposes when the code completes - The mutex keeps a queue of unfinished tasks that await a token and makes sure there is only one such token alive at any point
- The token itself is a disposable that runs the
Release
method when it is disposed.