public int AcquireLifetimeToken() { if (m_zeroReferencesLeft) { throw new InvalidOperationException(Res.TokenCountZero); } int next; lock (m_lifetimeTokens) { // Lazily initialize m_random for perf. if (m_random == null) { m_random = new Random(); } next = m_random.Next(); while (m_lifetimeTokens.Contains(next)) { next = m_random.Next(); } m_lifetimeTokens.Add(next); if (m_lifetimeTokens.Count == 1) { // Register as a sponsor the first time a token is aquired. // need to do this here instead of in InitializeLifetimeService because of a bug in remoting // involving security. RegisterAsSponsor(); // Increment ref count on appdomain owner if needed IContract owner = ContractHandle.AppDomainOwner(AppDomain.CurrentDomain); if (owner != null && owner != this) { m_tokenOfAppdomainOwner = owner.AcquireLifetimeToken(); } } } return(next); }
public void RevokeLifetimeToken(int token) { lock (m_lifetimeTokens) { if (!m_lifetimeTokens.Remove(token)) { throw new InvalidOperationException(Res.LifetimeTokenNotFound); } if (m_lifetimeTokens.Count == 0) { m_zeroReferencesLeft = true; // hook to allow subclasses to clean up OnFinalRevoke(); IContract owner = ContractHandle.AppDomainOwner(AppDomain.CurrentDomain); if (owner != null) { if (owner == this) { // Create a separate thread to unload this appdomain, because we // cannot shut down an appdomain from the Finalizer thread (though there // is a bug that allows us to do so after the first appdomain has been // unloaded, but let's not rely on that). // We can consider using an threadpool thread to do this, but that would add // test burden. SecurityPermission permission = new SecurityPermission(SecurityPermissionFlag.ControlThread); permission.Assert(); System.Threading.ThreadStart threadDelegate = new System.Threading.ThreadStart(AppDomainUnload); System.Threading.Thread unloaderThread = new System.Threading.Thread(threadDelegate); unloaderThread.Start(); } else { owner.RevokeLifetimeToken(m_tokenOfAppdomainOwner); } } } } }