Tridion - Event System Objects are Not Being Destroyed

tridion, tridion-2011

Solution

Life-cycle management for `TcmExtension` classes is quite simple:

when you call `Subscribe` the `TcmExtension` object you specify is added to an internal list of subscriptions

when you later call `Unsubscribe` the same `TcmExtension` object is removed from the list of subscriptions

Since you never call `Unsubscribe` your `WorkflowEventSystem` is never removed and thus will never be garbage collected by .NET. And since your `WorkflowEventSystem` holds a reference to the `PublishScheduler` instance it created, that one will thus also never be cleaned up.

The proper boilerplate for a custom `TcmExtension` is:

public class WorkflowEventSystem : TcmExtension, IDisposable
{
    EventSubscription _subscription;

    public WorkflowEventSystem()
    {
        this.Subscribe();
    }

    public void Subscribe()
    {
         _subscription = EventSystem.Subscribe<ProcessInstance, 
             FinishProcessEventArgs>(ScheduleForPublish, EventPhases.All);
    }

    public void Dispose()
    {
        _subscription.Unsubscribe();
    }
}

Nuno also gave a longer example (handling multiple subscribers) in this article: http://nunolinhares.blogspot.nl/2012/07/validating-content-on-save-part-1-of.html

Problem

I have created a `TcmExtension` named `WorkflowEventSystem` that has an event handler subscribed to the `FinishProcess` event. The purpose of this event is to schedule for publish all dependencies (i.e. pages) of the associated workflow subject. The problem I am having is that even though the event triggers at the right time (a workflow process is completed), and all the items that are supposed to be scheduled for publish are, the `PublishScheduler` object created by the event never seems to go out of scope, and as such the WorkflowEventSystem object does not either. Is there something I am missing about how the Event System works that would cause these objects to live on forever? I've included what I consider the relevant code below (some parts summarized). Thanks for any help. Here's most of the actual TcmExtension: ``` public class WorkflowEventSystem : TcmExtension { public WorkflowEventSystem() { this.Subscribe(); } public void Subscribe() { EventSystem.Subscribe<ProcessInstance, FinishProcessEventArgs>(ScheduleForPublish, EventPhases.All); } } ``` `ScheduleForPublish` creates a `PublishScheduler` object (class I created): ``` private void ScheduleForPublish(ProcessInstance process, FinishProcessEventArgs e, EventPhases phase) { if(phase == EventPhases.TransactionCommitted) { PublishScheduler publishScheduler = new PublishScheduler(process); publishScheduler.ScheduleForPublish(process); publishScheduler = null; // worth a try } } ``` The `ScheduleForPublish` method looks similar to this: ``` public void ScheduleForPublish(ProcessInstance process) { using(Session session = new Session("ImpersonationUser")) { var publishInstruction = new PublishInstruction(session); // Set up some publish Instructions var publicationTargets = new List<PublicationTarget>(); // Add a PublicationTarget here by tcm id IList<VersionedItem> itemsToPublish = new List<VersionedItem>(); // Add the items we want to publish by calling GetUsingItems(filter) // on the workflow process' subject //Publish the items PublishEngine.Publish(itemsToPublish.Cast<IdentifiableObject>(), publishInstruction, publishTargets); } } ```

Original source