If your thread exists to serve the object in the interests of other threads, you should have an open wrapper object for which all threads "interested" in the service will contain strong links, and the service itself will keep a long weak link. This wrapper object should not contain any information that the service should read or manipulate, but should forward all requests for information to an object that both the wrapper and the service contain strong links.
When the server thread is awake, it should periodically check to see if a weak reference to the wrapper object remains. If this is not the case, the server thread should be disconnected in an orderly manner. Note that the server never uses a strong reference to the wrapper β even temporarily β so the wrapper must evaporate as soon as no one is interested.
If the server thread can be blocked indefinitely, waiting for different things to happen, the shell should contain a single link anywhere in the universe for an object that can be finalized, which contains a strong link to the server object; when the finalizer finishes, it must check to see if the long weak link held by the server object retains it. If this is not the case, try to push the server thread (for example, using Monitor.TryEnter/Monitor.Pulse . If the wrapper object is still alive (finalizers can sometimes erroneously run in some resurrection scenarios), or the finalizer could not push the server thread, the final object must re-register to complete.
Using a finalizer object will complicate things; if the server thread can wake itself up periodically, without the need to push, which will simplify the design. However, the finalizer used as described should be relatively robust even in scenarios involving involuntary resurrection.
source share