Adding an Unamanaged Object to ADXOutlookItemEvents

Add-in Express™ Support Service
That's what is more important than anything else

Adding an Unamanaged Object to ADXOutlookItemEvents
Implmenting the Dispose Design Pattern in an ADX derived class 
German Hayles




Posts: 30
Joined: 2015-04-27
Recently I found it necessary to add a Timer (System.Timers.Timer) object to my class OutlookItemEventsClass. It's derived from AddinExpress.MSO.ADXOutlookItemEvents.

Experience tells me that when dealing with unmanaged resources in a class it's usually best to implement the Dispose Design Pattern. Below is a code snippet of what I did. I was wondering if I'd missed anything, or if there were any "Gotchas"


    public class OutlookItemEventsClass : AddinExpress.MSO.ADXOutlookItemEvents
    {
       

        static System.Timers.Timer _Timer = null; //UNMANAGED RESOURCE

        public OutlookItemEventsClass(AddinExpress.MSO.ADXAddinModule module): base(module)
        {

            _Timer = new System.Timers.Timer(1000);
            _Timer.Elapsed += new System.Timers.ElapsedEventHandler(WhatTheHey);
            _Timer.AutoReset = false;


        }

        #region Dispose Design pattern

        // Flag: has Dispose already been called?
        bool _disposed = false;

        // Public implementation of Dispose pattern callable by consumers.
        public override void Dispose()
        {
            base.Dispose(); // CALLING BASE CLASS DISPOSE
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        // Protected implementation of Dispose pattern.
        protected virtual void Dispose(bool disposing)
        {
            if (_disposed)
                return;

            if (disposing)
            {
                // Managed code gets freed here
            }

            // Unmanaged code gets freed here
            //
            if (_Timer != null)
            {
                log.Debug("Disposing _Timer resource");
                _Timer.Dispose();
                _Timer = null;
            }
            _disposed = true;

        }


        /// <summary>
        /// Finalizers are used in the case of a class containing unmanaged code
        /// "_Timer" is unmanaged
        /// </summary>
        ~OutlookItemEventsClass()
        {
            // Finalizer calls Dispose(false)  
            log.Info("Finalizer called for OutlookItemEventsClass");
            Dispose(false);
        }
        #endregion
     }
Posted 19 May, 2017 14:26:22 Top
Andrei Smolin


Add-in Express team


Posts: 14136
Joined: 2006-05-11
Hello German,

Since it is mentioned in the System.Timers namespace, I assume this is a managed object, not unmanaged one.

In a COM add-in you should only use System.Windows.Forms.Timer because this timer fires its event on the main thread. You may run into many, many issues when using a timer that fires its event on a background thread *if* you use any Office object model on that thread. The point is: all Office object models are not thread safe.

Regards from Belarus (GMT+3),

Andrei Smolin
Add-in Express Team Leader
Posted 22 May, 2017 06:03:11 Top
German Hayles




Posts: 30
Joined: 2015-04-27
Thanks!

I wasn't aware of System.Windows.Forms.Timer and the threading issue you brought up.

My only point of disagreement is about System.Timers. System.Timers.Timer has a call to "Dispose". I wouldn't think that Microsoft would provide a "Dispose" method on a managed object.

That said, I am going to follow your suggestion and switch over to System.Windows.Forms.Timer. I'd like to avoid any threading surprises as much as possible.
Posted 22 May, 2017 09:20:01 Top
Andrei Smolin


Add-in Express team


Posts: 14136
Joined: 2006-05-11
No problem.

Regards from Belarus (GMT+3),

Andrei Smolin
Add-in Express Team Leader
Posted 22 May, 2017 09:58:04 Top