Dan Rigsby – Coding Up Style

Developer.Speaker.Blogger

Archive for March, 2008

Async Operations in Wcf: Canceling Operations

Posted by Dan Rigsby on 30th March 2008

Async Operations in Wcf Series:
Part 1: Event Based Model
Part 2: IAsyncResult Model (Client-Side)
Part 3: IAsyncResult Model (Server-Side)
Part 4: Canceling Operations
Part 5: Handling Exceptions

This is the fourth in a four part series on asynchronous operations in Wcf.  If you are new to this series, you might want to read the first section of part one to get an introduction to this post: http://www.danrigsby.com/blog/index.php/2008/03/18/async-operations-in-wcf-event-based-model/

What is Canceling Wcf Operations

In some situations, when you submit an asynchronous call to the server, you might want to be able to cancel the operation.  Let’s say you have a query running that will may last over 30 seconds and the user navigates away.  Or suppose you are running an expensive database update and realize that you need to cancel the operation before it completes.

Windows Communication Foundation has no support for canceling operations and some pitfalls in trying to implement it are addressed here: http://blogs.msdn.com/drnick/archive/2007/12/27/cleaning-up-async.aspx.  This article will explain an approach to implement canceling support.  The process explained here uses a custom library called “Rigsby.AsyncOperation” and a class called “PendingOperationController”. This approach has one major pitfall: if an operation has completed, the best chance a cancel operation has may be to cancel the return to the client.  While this can save network bandwidth, the operation is still completed.  This can be undesirable in situations like a database update, but you there is little that can be done once everything in complete.  What this approach does offer is a way to cancel an operation that will try to cancel at multiple stages:

  1. If the operation is just sitting in the thread pool and hasn’t yet been processed, then it will be removed.
  2. If the operation is already running, then it will try to cancel the operation after it is complete.  It does this via a TransactionScope to attempt to rollback the operation.
  3. The operation itself can check the status of the request to check if it has been canceled at any time.  So if you have an operation which does 3 updates to the database, you can double check between each update if the request has been canceled, and if so bail out and let the TransactionScope roll back the pervious updates.

The PendingOperationController can also be used for other server-side asynchronous operations as well.  The controller could just be used to handle queuing of requests and signaling their completion.  This can make server-side code much cleaner while giving you the ability to add canceling support in the future.

What is AsyncOperation library

The AsyncOperation library is a custom library that can be used to assist with asynchronous operations in Wcf and provide support for cancellations.  (You can download the library here, but the code for each file is included inline as well.) The goal of this library and the PendingOperationController is all about extensibility and flexibility to work with many different systems and scenarios. The library contains 5 items:

1. AsyncStatus Enum

To convey the status of a pending operation, this enumeration contains all of the states that a pending operation can be in:

namespace Rigsby.AsyncOperation
{
    /// <summary>
    /// The status for an asynchronous operation.
    /// </summary>
    public enum AsyncStatus
    {
        /// <summary>
        /// The status is unknown.
        /// </summary>
        Unknown = 0,

        /// <summary>
        /// The asynchronous operation has not yet been started, but is queued up.
        /// </summary>
        Queued,

        /// <summary>
        /// The asynchronous operation has been started.
        /// </summary>
        Started,

        /// <summary>
        /// The asynchronous operation has completed.
        /// </summary>
        Completed,

        /// <summary>
        /// The asynchronous operation has been canceled.
        /// </summary>
        Canceled
    }
}

2. AsyncResult Class

This class was introduced in the IAsyncResult Model (Server-Side) article.  You could use the System.Runtime.Remoting.Messaging.AsyncResult, but many times you will want your own implementation of IAsyncResult.  I use a custom AsyncResult base class and inherit from it to add in properties and methods needed by the operations. Here is a base AsyncResult class that you can use:

using System;
using System.Threading;

namespace Rigsby.AsyncOperation
{
    /// <summary>
    /// The result of an asynchronous operation.
    /// </summary>
    public class AsyncResult : IAsyncResult, IDisposable
    {
        private AsyncCallback m_AsyncCallback;
        private object m_State;
        private ManualResetEvent m_ManualResentEvent;

        /// <summary>
        /// Initializes a new instance of the <see cref="AsyncResult"/> class.
        /// </summary>
        /// <param name="callback">The callback.</param>
        /// <param name="state">The state.</param>
        public AsyncResult(
            AsyncCallback callback,
            object state)
        {
            this.m_AsyncCallback = callback;
            this.m_State = state;
            this.m_ManualResentEvent = new ManualResetEvent(false);
        }

        /// <summary>
        /// Completes this instance.
        /// </summary>
        public virtual void OnCompleted()
        {
            m_ManualResentEvent.Set();
            if (m_AsyncCallback != null)
            {
                m_AsyncCallback(this);
            }
        }

        #region IAsyncResult Members
        /// <summary>
        /// Gets a user-defined object that qualifies or contains information about an asynchronous operation.
        /// </summary>
        /// <value></value>
        /// <returns>A user-defined object that qualifies or contains information about an asynchronous operation.</returns>
        public object AsyncState
        {
            get
            {
                return m_State;
            }
        }

        /// <summary>
        /// Gets a <see cref="T:System.Threading.WaitHandle"/> that is used to wait for an asynchronous operation to complete.
        /// </summary>
        /// <value></value>
        /// <returns>A <see cref="T:System.Threading.WaitHandle"/> that is used to wait for an asynchronous operation to complete.</returns>
        public System.Threading.WaitHandle AsyncWaitHandle
        {
            get
            {
                return m_ManualResentEvent;
            }
        }

        /// <summary>
        /// Gets an indication of whether the asynchronous operation completed synchronously.
        /// </summary>
        /// <value></value>
        /// <returns>true if the asynchronous operation completed synchronously; otherwise, false.</returns>
        public bool CompletedSynchronously
        {
            get
            {
                return false;
            }
        }

        /// <summary>
        /// Gets an indication whether the asynchronous operation has completed.
        /// </summary>
        /// <value></value>
        /// <returns>true if the operation is complete; otherwise, false.</returns>
        public bool IsCompleted
        {
            get
            {
                return m_ManualResentEvent.WaitOne(0, false);
            }
        }
        #endregion IAsyncResult Members

        #region IDisposable Members
        private bool m_IsDisposed = false;
        private event System.EventHandler m_Disposed;

        /// <summary>
        /// Gets a value indicating whether this instance is disposed.
        /// </summary>
        /// <value>
        ///     <c>true</c> if this instance is disposed; otherwise, <c>false</c>.
        /// </value>
        [System.ComponentModel.Browsable(false)]
        public bool IsDisposed
        {
            get
            {
                return m_IsDisposed;
            }
        }

        /// <summary>
        /// Occurs when this instance is disposed.
        /// </summary>
        public event System.EventHandler Disposed
        {
            add
            {
                m_Disposed += value;
            }
            remove
            {
                m_Disposed -= value;
            }
        }

        /// <summary>
        /// Releases unmanaged and - optionally - managed resources
        /// </summary>
        public void Dispose()
        {
            if (!m_IsDisposed)
            {
                this.Dispose(true);
                System.GC.SuppressFinalize(this);
            }
        }

        /// <summary>
        /// Releases unmanaged and - optionally - managed resources
        /// </summary>
        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
        protected virtual void Dispose(bool disposing)
        {
            try
            {
                if (disposing)
                {
                    m_ManualResentEvent.Close();
                    m_ManualResentEvent = null;
                    m_State = null;
                    m_AsyncCallback = null;

                    System.EventHandler handler = m_Disposed;
                    if (handler != null)
                    {
                        handler(this, System.EventArgs.Empty);
                        handler = null;
                    }
                }
            }
            finally
            {
                m_IsDisposed = true;
            }
        }

        /// <summary>
        ///    <para>
        ///        Checks if the instance has been disposed of, and if it has, throws an <see cref="ObjectDisposedException"/>; otherwise, does nothing.
        ///    </para>
        /// </summary>
        /// <exception cref="System.ObjectDisposedException">
        ///    The instance has been disposed of.
        ///    </exception>
        ///    <remarks>
        ///    <para>
        ///        Derived classes should call this method at the start of all methods and properties that should not be accessed after a call to <see cref="Dispose()"/>.
        ///    </para>
        /// </remarks>
        protected void CheckDisposed()
        {
            if (m_IsDisposed)
            {
                string typeName = GetType().FullName;

                // TODO: You might want to move the message string into a resource file
                throw new System.ObjectDisposedException(
                    typeName,
                    String.Format(System.Globalization.CultureInfo.InvariantCulture,
                        "Cannot access a disposed {0}.",
                        typeName));
            }
        }
        #endregion IDisposable Members
    }
}

3. PendingAsyncResult Class

This class is an extension of the AsyncResult class.  It is designed to contain all of the information needed as a operation moves through its stages.  Included in this are its status, the input values, and the output values:

  1. String Id property:  This is a simple identifier to distinguish the operation.  This should be a System.Guid value exposed as a string.  We can’t just use the IAsyncResult to identify the operation because it the SendAsyncResult class (discussed in the IAsyncResult Model (Server-Side) article) is not serializable.  Since we need to be able to identify the operation in order to cancel it or get it’s status, this is pretty important.
  2. Generic Input property: This property represents the input values.  It is quite possible and likely to have multiple input values for the operation you want this class to represent.  However to make this class be as flexible as possible, there is only a single generic input class.  If you have more than one input value, you should create an intermediate class that contains the different input values and use that class as the TInput template.  For example, if you have an “Addition” operation that takes in two numbers to add, you might have an Input class that contains two integers.
  3. Generic Output property: This property represents the out value of the operation.  This will always be a single value since that is all a method returns.  The type of the output value should be represented with the TOutput template.
  4. Events for status changes: For each of the major statuses there is an event that is fired for each.  You could feasibly change this to be a single event for all status changes, if you so choose.
  5. Methods for moving through statuses: To change statuses there is a method to move between the major statuses.  To move to the Canceled status, you would call the OnCanceled method, etc.
using System;

namespace Rigsby.AsyncOperation
{
    /// <summary>
    /// A pending asynchronous operation.
    /// </summary>
    public class PendingAsyncResult<TInput, TOutput> : AsyncResult
    {
        private string m_Id = String.Empty;
        private TInput m_Input;
        private TOutput m_Output;

        private EventHandler m_Canceled;
        private EventHandler m_Queued;
        private EventHandler m_Started;

        /// <summary>
        /// A generic object to perform a 'lock' on.
        /// </summary>
        protected object m_SyncRoot = new object();

        /// <summary>
        /// Protected implmenetation of <see cref="AsyncStatus"/>.
        /// </summary>
        protected AsyncStatus m_AsyncStatus;

        /// <summary>
        /// Gets or sets the async status.
        /// </summary>
        /// <value>The async status.</value>
        public AsyncStatus AsyncStatus
        {
            get
            {
                return m_AsyncStatus;
            }
        }

        /// <summary>
        /// Gets or sets the id.
        /// </summary>
        /// <value>The id.</value>
        public string Id
        {
            get
            {
                return m_Id;
            }
            set
            {
                m_Id = value;
            }
        }

        /// <summary>
        /// Gets or sets the input for the operation.
        /// </summary>
        /// <value>The input.</value>
        public TInput Input
        {
            get
            {
                return m_Input;
            }
            set
            {
                m_Input = value;
            }
        }

        /// <summary>
        /// Gets or sets the output of the operation.
        /// </summary>
        /// <value>The output.</value>
        public TOutput Output
        {
            get
            {
                return m_Output;
            }
            set
            {
                m_Output = value;
            }
        }

        #region Public Events
        /// <summary>
        /// Occurs when the operation has been canceled.
        /// </summary>
        public event EventHandler Canceled
        {
            add
            {
                m_Canceled += value;
            }
            remove
            {
                m_Canceled -= value;
            }
        }

        /// <summary>
        /// Occurs when the operation has been started.
        /// </summary>
        public event EventHandler Started
        {
            add
            {
                m_Started += value;
            }
            remove
            {
                m_Started -= value;
            }
        }

        /// <summary>
        /// Occurs when the operation has been eueued.
        /// </summary>
        public event EventHandler Queued
        {
            add
            {
                m_Queued += value;
            }
            remove
            {
                m_Queued -= value;
            }
        }
        #endregion Public Events

        #region Constructors
        /// <summary>
        /// Initializes a new instance of the <see cref="CancellableAsyncResult"/> class.
        /// </summary>
        /// <param name="callback">The callback.</param>
        /// <param name="state">The state.</param>
        public PendingAsyncResult(
            AsyncCallback callback,
            object state) : this(default(TInput), String.Empty, callback, state)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="CancellableAsyncResult"/> class.
        /// </summary>
        /// <param name="callback">The callback.</param>
        /// <param name="state">The state.</param>
        public PendingAsyncResult(
            string id,
            AsyncCallback callback,
            object state) : this(default(TInput), id, callback, state)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="CancellableAsyncResult"/> class.
        /// </summary>
        /// <param name="input">The input.</param>
        public PendingAsyncResult(
            TInput input,
            string id,
            AsyncCallback callback,
            object state) : base(callback, state)
        {
            m_Input = input;

            if (String.IsNullOrEmpty(id))
            {
                Id = Guid.NewGuid().ToString();
            }
            else
            {
                Id = id;
            }
        }
        #endregion Constructors

        /// <summary>
        /// Called when [queued].
        /// </summary>
        public virtual void OnQueued()
        {
            lock (m_SyncRoot)
            {
                if (m_AsyncStatus != AsyncStatus.Completed
                    && m_AsyncStatus != AsyncStatus.Canceled)
                {
                    m_AsyncStatus = AsyncStatus.Queued;
                }
            }

            EventHandler eventHandler = m_Queued;
            if (eventHandler != null)
            {
                eventHandler(this, EventArgs.Empty);
            }
        }

        /// <summary>
        /// Called when [started].
        /// </summary>
        public virtual void OnStarted()
        {
            lock (m_SyncRoot)
            {
                if (m_AsyncStatus != AsyncStatus.Completed
                    && m_AsyncStatus != AsyncStatus.Canceled)
                {
                    m_AsyncStatus = AsyncStatus.Started;
                }
            }

            EventHandler eventHandler = m_Started;
            if (eventHandler != null)
            {
                eventHandler(this, EventArgs.Empty);
            }
        }

        /// <summary>
        /// Cancels this instance.
        /// </summary>
        public virtual void OnCanceled()
        {
            lock (m_SyncRoot)
            {
                if (m_AsyncStatus != AsyncStatus.Completed)
                {
                    m_AsyncStatus = AsyncStatus.Canceled;
                }
            }

            EventHandler eventHandler = m_Canceled;
            if (eventHandler != null)
            {
                eventHandler(this, EventArgs.Empty);
            }
        }

        /// <summary>
        /// Completes this instance.
        /// </summary>
        public override void OnCompleted()
        {
            lock (m_SyncRoot)
            {
                m_AsyncStatus = AsyncStatus.Completed;
            }

            base.OnCompleted();
        }

        /// <summary>
        /// Releases unmanaged and - optionally - managed resources
        /// </summary>
        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                // Null out event to remove subscribers
                m_Started = null;
                m_Queued = null;
                m_Canceled = null;
            }

            base.Dispose(disposing);
        }
    }
}

One possible addition to this class could be to extend the concept of “status” to include more such as a “percent complete”.  It would be up to you how you would calculate the completion percent.

4. PendingOperationEventHandler Delegate

This delegate represents the method that the PendingOperationController will call when it is actually ready to do its work.  This method uses the same TInput and TOutput templates discussed in the PendingAsyncResult class.  For instance if this operation is a database insert, the method represented in this delegate would be the method that actually performs the database insert.

namespace Rigsby.AsyncOperation
{
    /// <summary>
    /// Represents a method that is called from a <see cref="PendingOperationController"/>.
    /// </summary>
    public delegate TOutput PendingOperationEventHandler<TInput, TOutput>(TInput data);
}

5. PendingOperationController Class

This is the heart of the AyncOperation library.  This class controls and monitors pending operations.  You could use this class if you implement canceling abilities or not.  This class is designed such that there is one PendingOperationController for each type of operation.  To instantiate the class you must specify the types for TInput and TOuput as well as the PendingOperationEventHandler delegate that represents the method that this class should call when executing the operation.  Once the class has been instantiated there three methods that can be called:

  1. AddPendingOperation: This method queues up an operation to be processed.  Each pending operation is added to the thread pool and the method is returned.  When a thread is available in the thread pool, the Callback method is called which checks to see if the operation has yet been canceled, then calls the method represented in the PendingOperationEventHandler delegate with the TInput and TOuput values from the PendingAsyncResult object.  The Callback method implements a TransactionScope.  At the end of the method, it checks one last time to see if the operation has been canceled.  If it has, then the the transaction is rolled back, otherwise the transaction completes and the client is signaled that the operation is complete.
  2. GetPendingOperationStatus:  This method returns the status of a pending operation in the queue.  If the operation is not found the “Unknown” result is returned.  This method may be called by the method represented in the PendingOperationEventHandler delegate to see if the operation has been canceled before proceeding on through the lines in the method.
  3. CancelPendingOperation: This method canceling pending operation.  It returns true if the operation has been canceled, and false if the operation cannot be canceled.  If this returns false, then the operation has probably already completed.
using System;
using System.Collections.Generic;
using System.Threading;

namespace Rigsby.AsyncOperation
{
    /// <summary>
    /// Controls pending asynchronous operations.
    /// </summary>
    /// <typeparam name="TInput">The type of the input.</typeparam>
    /// <typeparam name="TOutput">The type of the output.</typeparam>
    public class PendingOperationController<TInput, TOutput>
    {
        public ReaderWriterLockSlim m_PendingOperationsLock =
            new ReaderWriterLockSlim();
        private static Dictionary<string, PendingAsyncResult<TInput, TOutput>> m_PendingOperations =
            new Dictionary<string, PendingAsyncResult<TInput, TOutput>>();

        private PendingOperationEventHandler<TInput, TOutput> m_Operation;

        /// <summary>
        /// Initializes a new instance of the <see cref="PendingOperationController&lt;TInput, TOutput&gt;"/> class.
        /// </summary>
        /// <param name="operation">The operation that is called when a pending operation is running.</param>
        public PendingOperationController(
            PendingOperationEventHandler<TInput, TOutput> operation)
        {
            m_Operation = operation;
        }

        /// <summary>
        /// Adds the pending operation.
        /// </summary>
        /// <param name="asyncResult">The async result.</param>
        public void AddPendingOperation(
            PendingAsyncResult<TInput, TOutput> asyncResult)
        {
            m_PendingOperationsLock.EnterWriteLock();
            try
            {
                if (!m_PendingOperations.ContainsKey(asyncResult.Id))
                {
                    m_PendingOperations.Add(asyncResult.Id, asyncResult);
                }
                else
                {
                    m_PendingOperations[asyncResult.Id] = asyncResult;
                }
                asyncResult.OnQueued();
            }
            finally
            {
                m_PendingOperationsLock.ExitWriteLock();
            }

            ThreadPool.QueueUserWorkItem(
                new WaitCallback(
                    Callback), asyncResult);
        }

        /// <summary>
        /// Gets the pending operation status.
        /// </summary>
        /// <param name="operationId">The operation id.</param>
        /// <returns></returns>
        public AsyncStatus GetPendingOperationStatus(
            string operationId)
        {
            AsyncStatus status = AsyncStatus.Unknown;

            m_PendingOperationsLock.EnterReadLock();
            try
            {
                if (m_PendingOperations.ContainsKey(operationId))
                {
                    status = m_PendingOperations[operationId].AsyncStatus;
                }
            }
            catch (KeyNotFoundException)
            {
                // ignore
            }
            finally
            {
                m_PendingOperationsLock.ExitReadLock();
            }

            return status;
        }

        /// <summary>
        /// Cancels the pending operation.
        /// </summary>
        /// <param name="operationId">The operation id.</param>
        /// <returns>Whether or not the operation was canceled.  
        /// If false, then the operation has probably already completed or the operationId was not valid.</returns>
        public bool CancelPendingOperation(
            string operationId)
        {
            bool result = false;

            PendingAsyncResult<TInput, TOutput> asyncResult = null;
            m_PendingOperationsLock.EnterReadLock();
            try
            {
                if (m_PendingOperations.ContainsKey(operationId))
                {
                    asyncResult = m_PendingOperations[operationId];
                }
            }
            catch (KeyNotFoundException)
            {
                // ignore
            }
            finally
            {
                m_PendingOperationsLock.ExitReadLock();
            }

            if (asyncResult != null)
            {
                asyncResult.OnCanceled();
                result = true;
                RemovePendingOperation(operationId);
                asyncResult.Dispose();
            }

            return result;
        }

        /// <summary>
        /// Gets the pending operation result.
        /// </summary>
        /// <param name="asyncResult">The async result.</param>
        /// <returns></returns>
        public TOutput GetOperationResult(
            IAsyncResult asyncResult)
        {
            TOutput result;

            PendingAsyncResult<TInput, TOutput> myAsyncResult =
                (PendingAsyncResult<TInput, TOutput>)asyncResult;
            result = myAsyncResult.Output;
            myAsyncResult.AsyncWaitHandle.WaitOne();
            myAsyncResult.Dispose();

            return result;
        }

        private void Callback(
            object state)
        {
            PendingAsyncResult<TInput, TOutput> asyncResult =
                state as PendingAsyncResult<TInput, TOutput>;

            // Make sure the operation isn't canceled yet.
            if (asyncResult.AsyncStatus != AsyncStatus.Canceled
                && m_PendingOperations.ContainsKey(asyncResult.Id))
            {
                using (System.Transactions.TransactionScope transactionScope =
                    new System.Transactions.TransactionScope())
                {
                    try
                    {
                        asyncResult.OnStarted();
                        asyncResult.Output = m_Operation.Invoke(asyncResult.Input);
                    }
                    finally
                    {
                        if (asyncResult.AsyncStatus != AsyncStatus.Canceled)
                        {
                            // Mark transaction completed
                            transactionScope.Complete();

                            asyncResult.OnCompleted();
                        }

                        RemovePendingOperation(asyncResult.Id);
                    }
                }
            }
        }

        private void RemovePendingOperation(
            string operationId)
        {
            m_PendingOperationsLock.EnterWriteLock();
            try
            {
                if (m_PendingOperations.ContainsKey(operationId))
                {
                    PendingAsyncResult<TInput, TOutput> asyncResult = m_PendingOperations[operationId];
                    m_PendingOperations.Remove(operationId);
                }
            }
            catch (KeyNotFoundException)
            {
                // ignore
            }
            finally
            {
                m_PendingOperationsLock.ExitWriteLock();
            }
        }
    }
}

How to implement it

Continuing with the previous articles in this series, the example implementation in this article be a service that calculates a square root.  Normally this operation is very fast, so the service implements a 4 second thread sleep, so that we can show the asynchronous operations and allow time to cancel a pending operation.  To better understand these example you might want to look over the previous articles especially: IAsyncResult Model (Server-Side).

Contract

The contract is much like that in previous articles with the following changes:

  1. The BeginGetSquareRoot now takes in the operationId.  The client determines the operation id so that it can use that identifier to reference the pending operation in the future.  This parameter can be anywhere in the parameter list, but I recommend that it be the last parameter for the AysncCallback and object parameters which must always be the last two parameters in an asynchronous operation.  If your method takes in more or one parameters, they should be displayed first.
  2. The synchronous and asynchronous versions of the operation must have different names (not including the “Begin” prefix on the asynchronous method).  We couldn’t have a method called GetSquareRoot and BeginGetSquareRoot.  This would cause a runtime exception because both the synchronous and asynchronous versions of a method must have the same parameters.  Since we have added the operationId, the method names must be different.  If you need to keep the same names, you could pass in the operationId to the synchronous method as well, but this doesn’t make sense.  One option I recommend is to just append “Async” to the asynchronous versions of the methods.  So you could have GetSquareRoot and BeginGetSquareRootAsync.
  3. We have added a CancelGetSquareRoot method that can be used to cancel an asychronous operation.  This method returns a boolean value that represents if the cancellation succeeded or not.
[ServiceContract]
public interface IMyService
{
    [OperationContract]
    double FindSquareRoot(double value);

    [OperationContract(AsyncPattern=true)]
    IAsyncResult BeginGetSquareRoot(double value, string operationId, AsyncCallback callback, object state);

    double EndGetSquareRoot(IAsyncResult asyncResult);

    [OperationContract]
    bool CancelGetSquareRoot(
        string asyncResultID);
}

Service

Our service is actually much simpler in this version than in previous articles since much of the work has been pushed to the PendingOperationController.  In the constructor of the service we build the PendingOperationController for our GetSquareRoot operations.  The FindSquareRoot method is the method that actually does our calculations.  This is the method that the PendingOperationEventHandler delegate represents, and this is the method passed into the constructor of the PendingOperationController.  The Begin, End, and Cancel operations all just call into the corresponding methods in the PendingOperationController.  The Begin method does have to create the intial PendingAsyncResult object, but otherwise the code in this methods should be very short.

[ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Multiple)]
public class MyService : IMyService
{
    private PendingOperationController<double, double> m_GetSquareRootOperationController;

    public MyService()
    {
        // Create the pending operation controller
        m_GetSquareRootOperationController =
            new PendingOperationController<double, double>(
                new PendingOperationEventHandler<double, double>(FindSquareRoot));
    }

    #region IMyService Members
    public double FindSquareRoot(double value)
    {
        Thread.Sleep(4000); // Wait 4 seconds
        return Math.Sqrt(value);
    }

    public IAsyncResult BeginGetSquareRoot(double value, string operationId, AsyncCallback callback, object state)
    {
        // Create pending result
        PendingAsyncResult<double, double> asyncResult =
            new PendingAsyncResult<double, double>(value, operationId, callback, state);

        // Queue pending result
        m_GetSquareRootOperationController.AddPendingOperation(asyncResult);

        return asyncResult;
    }

    public double EndGetSquareRoot(IAsyncResult asyncResult)
    {
        // Get pending result
        return m_GetSquareRootOperationController.GetOperationResult(asyncResult);
    }

    public bool CancelGetSquareRoot(string operationId)
    {
        // Cancel pending result
        return m_GetSquareRootOperationController.CancelPendingOperation(operationId);
    }
    #endregion IMyService Members
}

Example Client

For our example client, we have a basic windows forms application where the user can enter a value, send it to the server, and the result will be displayed.  We have added a cancel button as well that can be used while the operation is being processed:

client

Here is the code behind this page.  The only tricky things here are the callback method that is passed to the BeginGetSquareRoot method and the call to the EndGetSquareRoot method from that callback method.  I explained these two methods in more depth in the IAsyncResult Model (Server-Side) article.  We have extended this by adding in a cancel method.  The form now needs to store the Id for the operation being run, so that this Id can be used to cancel the operation.

public partial class Form1 : Form
{
    IMyService m_Client;
    string m_MyOperationId;

    public Form1()
    {
        InitializeComponent();

        ChannelFactory<IMyService> factory = new ChannelFactory<IMyService>("netTcp");
        factory.Open();
        m_Client = factory.CreateChannel();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        double value = 0;
        Double.TryParse(m_ValueTextBox.Text, out value);

        m_MyOperationId = Guid.NewGuid().ToString();

        m_Client.BeginGetSquareRoot(value, m_MyOperationId, new AsyncCallback(OnEndGetSquareRoot), null);

        m_StartButton.Enabled = false;
        m_CancelButton.Enabled = true;
        m_ResultTextBox.Text = "Loading...";
    }

    private void m_CancelButton_Click(object sender, EventArgs e)
    {
        bool canceled = m_Client.CancelGetSquareRoot(m_MyOperationId);

        m_StartButton.Enabled = canceled;
        m_CancelButton.Enabled = false;

        if (canceled)
        {
            m_ResultTextBox.Text = "Canceled";
        }
    }

    public void OnEndGetSquareRoot(IAsyncResult asyncResult)
    {
        if (this.IsHandleCreated && !this.IsDisposed)
        {
            this.Invoke(
                new MethodInvoker(delegate()
                {
                    m_ResultTextBox.Text = m_Client.EndGetSquareRoot(asyncResult).ToString();

                    m_StartButton.Enabled = true;
                    m_CancelButton.Enabled = false;
                }));
        }
    }
}

Notice that in the OnEndGetSquareRoot method, we can invoking the operation using “this.Invoke”.  This ensures that the operation is called on the UI thread since we are updating a UI element.  We know that OnEndGetSquareRoot is called by the signal on the server, so the method is always called by a thread from the server.

You can download a complete sample of the code discussed in this article here: http://www.danrigsby.com/Files/Rigsby.WcfAsyncOperation.zip

Posted in Wcf | 9 Comments »

How to grayout an image in .Net

Posted by Dan Rigsby on 28th March 2008

Here is a handy method for making a grayscale version of an image.  I use this method a lot to grayout icons that I wish to show as disabled.  All you need to do is pass in the image and it will apply a grayscale over it.  The key to getting all of this to work is the ColorMatrix.  There is a detailed article about how this works on codeproject: http://www.codeproject.com/KB/GDI-plus/colormatrix.aspx.

public static void ApplyGrayscale(
    ref Image image)
{
    // Build color matrix set at 1/3
    ColorMatrix matrix = new ColorMatrix();
    matrix[0, 0] = 1/3f;
    matrix[0, 1] = 1/3f;
    matrix[0, 2] = 1/3f;
    matrix[1, 0] = 1/3f;
    matrix[1, 1] = 1/3f;
    matrix[1, 2] = 1/3f;
    matrix[2, 0] = 1/3f;
    matrix[2, 1] = 1/3f;
    matrix[2, 2] = 1/3f;

    // Create image attributes that will applied to the image
    ImageAttributes attributes = new ImageAttributes();
    attributes.SetColorMatrix(matrix);

    Graphics g = null;
    try
    {
        // Get the graphics object from the image
        g = Graphics.FromImage(image);

        // Redraw the image on the graphics object using the grayscale color matrix
        g.DrawImage(image,
            new Rectangle(0, 0, image.Width, image.Height),
            0,
            0,
            image.Width,
            image.Height,
            GraphicsUnit.Pixel,
            attributes);
    }
    finally
    {
        if (g != null)
        {
            g.Dispose();
        }
    }
}

 

Here are some sample before and after images (of my daughter Claire):

claire clairegray

 

Here is another example with a more typical line-of-business image:

disk_blue disk_bluegray

 

To make this easier to try out or use, I have wrapped the method into a executable as well.  You can download the source for this here: http://www.danrigsby.com/Files/Rigsby.ImageUtilities.Grayscale.zip

To run the program, compile the code and execute the exe file while passing in the source file name and the file name you want to save the new grayscaled image to, like this:

Rigsby.ImageUtilities.Grayscale.exe "c:\Claire.jpg" "c:\Claire-Gray.jpg"
 

Posted in .Net, Common Libraries | 9 Comments »

Making "Public" Resources Files: PublicResxFileCodeGenerator

Posted by Dan Rigsby on 27th March 2008

This is probably one of my favorite minor additions to Visual Studio 2008, that you probably haven heard of. 

In previous versions of Visual Studio, if you created strongly typed resources files, all of the properties were “internal”.  If you wanted to expose these properties outside of the assembly, you ran into issues.  You could use a custom tool such as ResxFileCodeGeneratorEx, but that meant that each developer had to have this tool installed and you would manually have to change the custom tool name in the properties window for the resource file:

Properties

You could also make the properties public by running resgen.exe with the /publicClass attribute, but you could not do this directly through Visual Studio.  You would have to create a pre-build event to call resgen like this:

resgen.exe "myfile.rex" /publicClass /str:c#

Now, in Visual Studio 2008 there is another option which should basically make these other options obsolete.  When you are working on the strongly typed resource file, there is a new drop down list at the top of the designer that allows you to change the access modifier to either “internal” or “public”.  This will cause the strongly typed resource “code behind” file to generate properties with the selected access modfier.

Resources

You could also manually set the custom tool to use this new generator in the properties window like so:

Properties2

All of these tools and procedures generate a code behind file (typically named something like resources.designer.cs) that contains the strongly typed resource information.  This file is automatically generated by Visual Studio when the resource file itself is changed.  If you were to go in and change the resource.resx file inside of a text editor, the strongly typed code file would not reflect these changes unless you ran resgen.exe afterwards, or opened the project again in Visual Studio.

Posted in Visual Studio | No Comments »

Async Operations in Wcf: IAsyncResult Model (Server-Side)

Posted by Dan Rigsby on 26th March 2008

Async Operations in Wcf Series:
Part 1: Event Based Model
Part 2: IAsyncResult Model (Client-Side)
Part 3: IAsyncResult Model (Server-Side)
Part 4: Canceling Operations
Part 5: Handling Exceptions

This is the third in a four part series on asynchronous operations in Wcf.  If you are new to this series, you might want to read the first section of part one to get an introduction to this post: http://www.danrigsby.com/blog/index.php/2008/03/18/async-operations-in-wcf-event-based-model/

What is the IAsyncResult Model (Server-Side)

The IAsyncResult Model (Server-Side) basically allows you to send a request to the server and the server will callback when the result is ready.  Inside the “callback” method you can send another request to get the actual result.   It is important to note though that this callback method will be invoked on a thread from the server.  So, if you are working with UI code you will need to check if InvokeRequired and Invoke the operation on the UI thread (there is an example of this below).

The IAsyncResult Model (Server-Side) in Wcf is what I call “server-side asynchronous”.  This means that the operations to the server are done completely asynchronously.  The IAsyncResult Model can work as “client-side asynchronous” which was discussed in the previous article: IAsyncResult Model (Client-Side).

There are a few benefits for using “server-side asynchronous” model over a “client-side asynchronous”:

  1. The client doesn’t have to create extra threads.  The can limit programming confusion and help conserve resources on the client.
  2. Opens the door for operations such as canceling an operation or getting the status of a pending operation.  If a “client-side asynchronous” model is used, the operation to the server is done synchronously so there is no way to perform these operation.
  3. Allows the use of both ChannelFactory<> and ClientBase<>  to connect to the server.  In the “client-side asynchronous” model only a ClientBase<> can be used.

How to implement it

AsyncResult Class

The patterns works off of the standard IAsyncResult interface.  You could use the System.Runtime.Remoting.Messaging.AsyncResult, but many times you will want your own implementation of IAsyncResult.  I use a custom AsyncResult base class and inherit from it to add in properties and methods needed by the operations. Here is a base AsyncResult class that you can use:

using System;
using System.Threading;

namespace Rigsby.AsyncOperation
{
    /// <summary>
    /// The result of an asynchronous operation.
    /// </summary>
    public class AsyncResult : IAsyncResult, IDisposable
    {
        private AsyncCallback m_AsyncCallback;
        private object m_State;
        private ManualResetEvent m_ManualResetEvent;

        /// <summary>
        /// Initializes a new instance of the <see cref="AsyncResult"/> class.
        /// </summary>
        /// <param name="callback">The callback.</param>
        /// <param name="state">The state.</param>
        public AsyncResult(
            AsyncCallback callback,
            object state)
        {
            this.m_AsyncCallback = callback;
            this.m_State = state;
            this.m_ManualResetEvent = new ManualResetEvent(false);
        }

        /// <summary>
        /// Completes this instance.
        /// </summary>
        public virtual void OnCompleted()
        {
            m_ManualResetEvent.Set();
            if (m_AsyncCallback != null)
            {
                m_AsyncCallback(this);
            }
        }

        #region IAsyncResult Members
        /// <summary>
        /// Gets a user-defined object that qualifies or contains information about an asynchronous operation.
        /// </summary>
        /// <value></value>
        /// <returns>A user-defined object that qualifies or contains information about an asynchronous operation.</returns>
        public object AsyncState
        {
            get
            {
                return m_State;
            }
        }

        /// <summary>
        /// Gets a <see cref="T:System.Threading.WaitHandle"/> that is used to wait for an asynchronous operation to complete.
        /// </summary>
        /// <value></value>
        /// <returns>A <see cref="T:System.Threading.WaitHandle"/> that is used to wait for an asynchronous operation to complete.</returns>
        public System.Threading.WaitHandle AsyncWaitHandle
        {
            get
            {
                return m_ManualResetEvent;
            }
        }

        /// <summary>
        /// Gets an indication of whether the asynchronous operation completed synchronously.
        /// </summary>
        /// <value></value>
        /// <returns>true if the asynchronous operation completed synchronously; otherwise, false.</returns>
        public bool CompletedSynchronously
        {
            get
            {
                return false;
            }
        }

        /// <summary>
        /// Gets an indication whether the asynchronous operation has completed.
        /// </summary>
        /// <value></value>
        /// <returns>true if the operation is complete; otherwise, false.</returns>
        public bool IsCompleted
        {
            get
            {
                return m_ManualResetEvent.WaitOne(0, false);
            }
        }
        #endregion IAsyncResult Members

        #region IDisposable Members
        private bool m_IsDisposed = false;
        private event System.EventHandler m_Disposed;

        /// <summary>
        /// Gets a value indicating whether this instance is disposed.
        /// </summary>
        /// <value>
        ///     <c>true</c> if this instance is disposed; otherwise, <c>false</c>.
        /// </value>
        [System.ComponentModel.Browsable(false)]
        public bool IsDisposed
        {
            get
            {
                return m_IsDisposed;
            }
        }

        /// <summary>
        /// Occurs when this instance is disposed.
        /// </summary>
        public event System.EventHandler Disposed
        {
            add
            {
                m_Disposed += value;
            }
            remove
            {
                m_Disposed -= value;
            }
        }

        /// <summary>
        /// Releases unmanaged and - optionally - managed resources
        /// </summary>
        public void Dispose()
        {
            if (!m_IsDisposed)
            {
                this.Dispose(true);
                System.GC.SuppressFinalize(this);
            }
        }

        /// <summary>
        /// Releases unmanaged and - optionally - managed resources
        /// </summary>
        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
        protected virtual void Dispose(bool disposing)
        {
            try
            {
                if (disposing)
                {
                    m_ManualResentEvent.Close();
                    m_ManualResentEvent = null;
                    m_State = null;
                    m_AsyncCallback = null;

                    System.EventHandler handler = m_Disposed;
                    if (handler != null)
                    {
                        handler(this, System.EventArgs.Empty);
                        handler = null;
                    }
                }
            }
            finally
            {
                m_IsDisposed = true;
            }
        }

        /// <summary>
        ///    <para>
        ///        Checks if the instance has been disposed of, and if it has, throws an <see cref="ObjectDisposedException"/>; otherwise, does nothing.
        ///    </para>
        /// </summary>
        /// <exception cref="System.ObjectDisposedException">
        ///    The instance has been disposed of.
        ///    </exception>
        ///    <remarks>
        ///    <para>
        ///        Derived classes should call this method at the start of all methods and properties that should not be accessed after a call to <see cref="Dispose()"/>.
        ///    </para>
        /// </remarks>
        protected void CheckDisposed()
        {
            if (m_IsDisposed)
            {
                string typeName = GetType().FullName;

                // TODO: You might want to move the message string into a resource file
                throw new System.ObjectDisposedException(
                    typeName,
                    String.Format(System.Globalization.CultureInfo.InvariantCulture,
                        "Cannot access a disposed {0}.",
                        typeName));
            }
        }
        #endregion IDisposable Members
    }
}
Continuing with our square root service from the previous articles, we will want to extend this base AyncResult class to hold both the input and output values for our operation.  You could have multiple input values such as two numbers you want to add.  In which case you could either have two input values stored in this class or create a “container” class that stores both of the numbers you wish to add.  Since our example has only one input value, our AsyncResult object for determining a square root could look like this:
 
public class GetSquareRootAsyncResult : AsyncResult
{
    private double m_Value;
    private double m_Result;

    public double Value
    {
        get { return m_Value; }
        set { m_Value = value; }
    }

    public double Result
    {
        get { return m_Result; }
        set { m_Result = value; }
    }

    public GetSquareRootAsyncResult(
        AsyncCallback callback,
        object state) : base (callback, state)
    {
    }
}

Contract

For our service contract, we have the GetSquareRoot method which will act as our synchronous version of the operation.  There are 2 new methods here called BeginGetSquareRoot and EndGetSquareRoot.  You must prefix these methods with “Begin” and “End”.  The “Begin” method must return IAsyncResult and the last two parameters must be an AsyncCallback and an object that represents the state.  The “End” method must have a single parameter for the IAsyncResult.  The return value of the “End” method represents the actual result of the operation.  Notice that only the “Begin” version of the the method is decorated with the OperationContract attribute and not the “End” method.  This is important for how these operations are wired up.  As long as you have “AsyncPattern=true” on the “Begin” method’s OperationContract attribute, the service and client will know to look for a corresponding “End” method.

[ServiceContract]
public interface IMyService
{
    [OperationContract]
    double GetSquareRoot(double value);

    [OperationContract(AsyncPattern=true)]
    IAsyncResult BeginGetSquareRoot(double value, AsyncCallback callback, object state);

    double EndGetSquareRoot(IAsyncResult asyncResult);
}

Service

Our service is basically a bare bones implementation of the contract.  The GetSquareRoot method is our synchronous operation and implements a 4 second thread sleep command to simulate the operation taking longer than what it really does.  This will be important when testing the asynchronous vs. the synchronous versions of the method.  Otherwise both methods would return in less than a second.

The BeingGetSquareRoot method creates a new instance of our GetSquareRootAsyncResult class and populates it with the value that we want to get the square root of.  The operation is then pushed into the threadpool and the IAsyncResult is returned from the method.  Once in the threadpool, the operation will be processed when the next thread is available by the Callback method.  The Callback method, executes the operation and calls the OnCompleted method on the GetSquareRootAsyncResult object which in turn signals the callback method on the client.

The EndGetSquareRoot method is will be called by callback method on the client to retrieve the value stored on the server after the client has been signaled.  This method basically just casts the IAsyncResult object passed to it as the GetSquareRootAsyncResult type and returns the value.  You might be asking yourself why the client can’t just do that itself.  The reason is that the IAsyncResult object passed to the client isn’t the actual object on the server, but basically a reference pointer that is passed to the client that the client can send back to the server to identity the object in the server’s memory. (The IAsyncResult returned to the client is of type System.ServiceModel.Channels.ServiceChannel.SendAsyncResult, but you wont find much about this class on msdn or anywhere else on the web.)

Here is an example of a service written against our contract for the GetSquareRoot service:

[ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Multiple)]
public class MyService : IMyService
{
    #region IMyService Members
    public double GetSquareRoot(double value)
    {
        Thread.Sleep(4000); // Wait 4 seconds
        return Math.Sqrt(value);
    }

    public IAsyncResult BeginGetSquareRoot(double value, AsyncCallback callback, object state)
    {
        GetSquareRootAsyncResult asyncResult =
            new GetSquareRootAsyncResult(callback, state);
        asyncResult.Value = value;

        ThreadPool.QueueUserWorkItem(
            new WaitCallback((Callback)),
            asyncResult);

        return asyncResult;
    }

    public double EndGetSquareRoot(IAsyncResult asyncResult)
    {
        double result = 0;

        using (GetSquareRootAsyncResult getSquareRootAsyncResult =
            asyncResult as GetSquareRootAsyncResult)
        {
            getSquareRootAsyncResult.AsyncWaitHandle.WaitOne();
            result = getSquareRootAsyncResult.Result;
        }

        return result;
    }
    #endregion IMyService Members

    private void Callback(object asyncResult)
    {
        GetSquareRootAsyncResult getSquareRootAsyncResult
            = (GetSquareRootAsyncResult)asyncResult;
        try
        {
            getSquareRootAsyncResult.Result =
                GetSquareRoot(getSquareRootAsyncResult.Value);
        }
        finally
        {
            getSquareRootAsyncResult.OnCompleted();
        }
    }
}

Example Client

For our example client, we have a basic windows forms application where the user can enter a value, send it to the server, and the result will be displayed:

SquareRoot

Here is the code behind this page.  The only tricky things here are the callback method that is passed to the BeginGetSquareRoot method and the call to the EndGetSquareRoot method from that callback method.

public partial class Form1 : Form
{
    IMyService m_Client;

    public Form1()
    {
        InitializeComponent();

        ChannelFactory<IMyService> factory =
            new ChannelFactory<IMyService>("netTcp");
        factory.Open();
        m_Client = factory.CreateChannel();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        double value = 0;
        Double.TryParse(m_ValueTextBox.Text, out value);

        m_Client.BeginGetSquareRoot(
            value,
            new AsyncCallback(OnEndGetSquareRoot),
            null);

        m_StartButton.Enabled = false;
        m_ResultTextBox.Text = "Loading...";
    }

    public void OnEndGetSquareRoot(IAsyncResult asyncResult)
    {
        this.Invoke(
            new MethodInvoker(delegate()
            {
                m_ResultTextBox.Text =
                    m_Client.EndGetSquareRoot(asyncResult).ToString();

                m_StartButton.Enabled = true;
            }));
    }
}
 

Notice that in the OnEndGetSquareRoot method, we can invoking the operation using “this.Invoke”.  This ensures that the operation is called on the UI thread since we are updating a UI element.  We know that OnEndGetSquareRoot is called by the signal on the server, so the method is always called by a thread from the server.

You can download a complete sample of the code discussed in this article here: http://www.danrigsby.com/Files/Rigsby.ServerSideIAsyncResultOperation.zip

Posted in Wcf | 8 Comments »

Async Operations in Wcf: IAsyncResult Model (Client-Side)

Posted by Dan Rigsby on 20th March 2008

Async Operations in Wcf Series:
Part 1: Event Based Model
Part 2: IAsyncResult Model (Client-Side)
Part 3: IAsyncResult Model (Server-Side)
Part 4: Canceling Operations
Part 5: Handling Exceptions

This is the second in a four part series on asynchronous operations in Wcf.   If you are new to this series, you might want to read the first section of part one to get an introduction to this post: http://www.danrigsby.com/blog/index.php/2008/03/18/async-operations-in-wcf-event-based-model/

What is the IAsyncResult Model (Client-Side)

The IAsyncResult Model (Client-Side) basically allows you to send a request to the server and the server will callback when the result is ready.  Inside the “callback” method you can send another request to get the actual result.   It is important to note though that this callback method will be on a thread from the server.  So if you are working with UI code you will need to check if InvokeRequired and Invoke the operation on the UI thread (there is an example of this below). You could also look at using the Event Based Model which does come back on the main UI thread, or look at setting up a SynchronizationContext.

The IAsyncResult Model (Client-Side) in Wcf is what I call “client-side asynchronous”.  This means that the operations to the server are still done synchronously, but the client does all of the dirty to work to make it appear asynchronous to the calling method.  The IAsyncResult Model can work as both “client-side asynchronous” and “sever-side asynchronous”, but we will get into the server-side this in the next article.  There are a lot of benefits to a “sever-side asynchronous” model.  If you are considering using the IAsyncResult Model (Client-Side), you might want to at least read over the IAsyncResult Model (Server-Side), to see if the benefits are of value to you.

Here is an example using the IAsyncResult Model (Client-Side) in Wcf:

ServiceReference.MyServiceClient m_Client;

public Form1()
{
    InitializeComponent();

    m_Client = new ServiceReference.MyServiceClient();
    m_Client.BeginGetSquareRoot(value, new AsyncCallback(OnEndGetSquareRoot), null);
}

void OnEndGetSquareRoot(IAsyncResult asyncResult)
{
    this.Invoke(
        new MethodInvoker(delegate()
        {
            MessageBox(m_Client.EndGetSquareRoot(asyncResult).ToString());
        }));
}
 

Notice how the callback method is wrapped in an Invoke statement. This is to ensure that the code in the delegate is executed by the main UI thread.

If this class is firing multiple asynchronous events, you will need some way to know which request the AsyncCallback correlates to.  To achieve this, you can use the “object UserState” parameter populate some unique value such as a Guid.  Then in the returned AsyncCallback, you can check the “asyncResult.AsyncState” to see if it matches the unique value for a particular operation.  You could accomplish this like so:

ServiceReference.MyServiceClient m_Client;
string m_MyOperationId;

public Form1()
{
    InitializeComponent();

    m_Client = new ServiceReference.MyServiceClient();

    m_MyOperationId = Guid.NewGuid().ToString();
    m_Client.BeginGetSquareRoot(value, new AsyncCallback(OnEndGetSquareRoot), m_MyOperationId);
}

void OnEndGetSquareRoot(IAsyncResult asyncResult)
{
    m_ResultTextBox.Invoke(
        new MethodInvoker(delegate()
        {
            if (asyncResult.AsyncState.ToString() == m_MyOperationId)
            {
                MessageBox(m_Client.EndGetSquareRoot(asyncResult).ToString());
            }
        }));
}

How to enable it?

The event based model requires .Net version 3.5 and only works if you are using a generated proxy or some class that derivess from System.ServiceModel.ClientBase.  This approach cannot be used with a client generated through a ChannelFactory, since it relies on the InvokeAsync method in the ClientBase class.  This doesn’t mean you have to use a generated proxy though.  You can still hand code a ClientBase on your own and take advantage of this.  This nice thing about this method is that there is no work to be done on the service side.  So if you are working with an existing service, you don’t have to worry about having to modify the existing code.

To build the proxy you could go through the command line and use svcutil.exe to generate the proxy like so:

svcutil http://localhost:8000/MyService/mex /async

Note you could also use the option “/tcv:Version35:”.  If you add this, then both the IAsyncResult Model and Event Based Model methods will be generated.

Or you could generate the proxy through Visual Studio with the “Add Service Reference” wizard. The first thing you might notice is that this wizard has a lot of new features compared to the Visual Studio 2005 version.  In the first screen, enter the address to the service wsdl, click “Go” to download the wsdl, then click on the “Advanced” button at the bottom of the window for more options:

AddService1

This will bring up an advanced window for “Service Reference Settings”.  Just check the box for “Generate asynchronous operations”.  This will cause the wizard to generate both the IAsyncResult Model and Event Based Model methods into your proxy classes (there is no way to tell it to just generate the IAsyncResult Model methods in .Net 3.5):

AddService2

The generated proxy will contain the following items for use with the IAsyncResult  Model (Client-Side):

  1. BeginMyOperation methods: For every operation, a new method is created whose same name is the operation name with “Begin” prepended at the front. These methods are used to initiate the asynchronous operation.  They always have a return result of “IAsyncResult” and add 2 new parameters at the of the list:
    1. “System.AsyncCallBack callback”: This is the callback method to call when the operation is complete.  The method signature must match the System.AsyncCallBack delegate.
    2. “object asyncState”: An object that represents the state of the asynchronous call.  This object can be used to pass information from the calling method to the callback method.  This could be used to pass a unique identifier for the operation such as a Guid or any other data.
  2. EndMyOperation methods: For every operation, a new method is created whose same name is the operation name with “Begin” prepended at the front. These methods are used to retrieve the actual return result of the operation from within the AsyncCallback method. These methods return the result that would be returned from the original synchronous method and take in the IAsyncResult of the operation results to retrieve.

There are other items added to the proxy code when selecting this option. Some of these are private methods used internally to wire up the IAsyncResult Model operations.  If you are using .Net 3.5, some of these new methods are used for the Event Based Model.

Note that every method in the service gets an Begin and End version when you generate the proxy through SvcUtil or in Visual Studio.  If you only want a select number of asynchronous methods, you could always manually remove the addition methods, or you could manually create your own classes and not rely on the generated proxies.  If you are going to hand code proxies, I recommend that you generate them first, and use that code as an example to build on.

You can download a complete sample of the code discussed in this article here: http://www.danrigsby.com/Files/Rigsby.ClientSideIAsyncResultOperation.zip

Posted in Wcf | 8 Comments »

Async Operations in Wcf: Event Based Model

Posted by Dan Rigsby on 18th March 2008

Async Operations in Wcf Series:
Part 1: Event Based Model
Part 2: IAsyncResult Model (Client-Side)
Part 3: IAsyncResult Model (Server-Side)
Part 4: Canceling Operations
Part 5: Handling Exceptions

This is the first in a four part series on asynchronous operations in Wcf.   Asynchronous operations allow for a client to send a request to the server and have the server callback to the client when the operation is complete.  This frees up the client to do other things and gets around any message timeout issues.

Wcf applications can achieve asynchronous requests in two ways (as described in Async Programming Design Patterns):

  1. Event Based Model: Event based asynchronous operations (see Event-based Asynchronous Pattern). This occurs on the client-side only.
  2. IAsyncResult Model: Asynchronous operations using System.IAsyncResult based object (see IAsyncResult Pattern). This can occur on the client-side or server-side.

This series will cover 4 areas including the Event Based Model, the IAsyncResult Model (client-side), the IAsyncResult Model (server-side), and a fourth article about how you could extend the IAsyncResult Model to support canceling an operation.   All of the examples used will be based on a Wcf Service that can be used to get the square root of a number.  A synchronous method to do this might be called something like “double GetSquareRoot(double number)”.  Our asynchronous methods will build on top of this. Thread.Sleep(4000) is called on this method on the service to make the method wait for 4 seconds.  This is necessary because otherwise the service would return the result very quickly, and you wouldn’t be able to really tell that it running asynchronously.  In a real production system, the service would be doing something much more time intensive such as a long database query.

In this first article, we will looking at the Event Based Model in depth.

What is the Event Based Model

The Event Based Model basically allows you to subscribe to an event for completed operations and then send the operation to the server.  When the operation is complete the method you used to subscribe to the event will be called and you can process the results.  It is important to note though that this callback method will be called on the same thread that was used to call the method.  This can be good if you are in a windows forms environment and need thing to execute on the main UI thread.  However if you want to look thread that called the method you can’t really do this.  So if you wanted to look at the calling thread’s culture for instance and maybe format the datetime or number values differently, then you are out of luck.  If you need to know what thread called the callback method, you might want to consider using the IAsyncResult Model.

The Event Based Model in Wcf is what I call “client-side asynchronous”.  This means that the operations to the server are still done synchronously, but the client does all of the dirty to work to make it appear asynchronous to the calling method.  The IAsyncResult Model can work as both “client-side asynchronous” and “sever-side asynchronous”, but we will get into this in the next article.  There are a lot of benefits to a “sever-side asynchronous” model.  If you are considering using the Event Based Model, you might want to at least read over the IAsyncResult Based “sever-side asynchronous” Model to see if the benefits are of value to you.

Here is an example using the Event Based Model in Wcf:

ServiceReference.MyServiceClient m_Client;

public Form1()
{
    InitializeComponent();

    m_Client = new ServiceReference.MyServiceClient();
    m_Client.GetSquareRootCompleted +=
        new EventHandler<ServiceReference.GetSquareRootCompletedEventArgs>(client_GetSquareRootCompleted);
    m_Client.GetSquareRootAsync(value);
}

void client_GetSquareRootCompleted(
    object sender,
    Rigsby.EventBasedWcfAsyncOperation.ServiceReference.GetSquareRootCompletedEventArgs e)
{
    MessageBox.Show(e.Result.ToString());
}

 

If this class is firing multiple asynchronous events, you will need some way to know which request the EventArgs correlates to.  To achieve this, there is a overloaded Async method that takes in an “object UserState”.  You can use this to populate some unique value such as a Guid.  Then in the returned EventArgs you can check the “e.UserState” to see if it matches the unique value for a particular operation.  You could accomplish this like so:

ServiceReference.MyServiceClient m_Client;
string m_MyOperationId;

public Form1()
{
    InitializeComponent();

    m_Client = new ServiceReference.MyServiceClient();
    m_Client.GetSquareRootCompleted +=
        new EventHandler<ServiceReference.GetSquareRootCompletedEventArgs>(client_GetSquareRootCompleted);

    m_MyOperationId = Guid.NewGuid().ToString();
    m_Client.GetSquareRootAsync(value, m_MyOperationId);
}

void client_GetSquareRootCompleted(
    object sender,
    Rigsby.EventBasedWcfAsyncOperation.ServiceReference.GetSquareRootCompletedEventArgs e)
{
    if ((string)e.UserState == m_MyOperationId)
    {
        MessageBox.Show(e.Result.ToString());
    }
}

 

The full Event Based Pattern allows for progress updates and the ability to cancel a running operation.  Wcf doesn’t support either of these at this time.  We will look at ways to cancel async operations in a later article.

How to enable it?

The event based model requires .Net version 3.5 and only works if you are using a generated proxy or some class that derivess from System.ServiceModel.ClientBase.  This approach cannot be used with a client generated through a ChannelFactory, since it relies on the InvokeAsync method in the ClientBase class.  This doesn’t mean you have to use a generated proxy though.  You can still hand code a ClientBase on your own and take advantage of this.  This nice thing about this method is that there is no work to be done on the service side.  So if you are working with an existing service, you don’t have to worry about having to modify the existing code.

To build the proxy you could go through the command line and use svcutil.exe to generate the proxy like so:

svcutil http://localhost:8000/MyService/mex /async /tcv:Version35

Note the option “/tcv:Version35:”.  If you don’t add this, then only the IAsyncResult Model methods will be generated.

Or you could generate the proxy through Visual Studio with the “Add Service Reference” wizard.  You need to make sure that you project is targeted for “.Net Framework 3.5″, otherwise it will just generate the IAsyncResult Model methods. The first thing you might notice is that this wizard has a lot of new features compared to the Visual Studio 2005 version.  In the first screen, enter the address to the service wsdl, click “Go” to download the wsdl, then click on the “Advanced” button at the bottom of the window for more options:

AddService1

This will bring up an advanced window for “Service Reference Settings”.  Just check the box for “Generate asynchronous operations”.  This will cause the wizard to generate both the IAsyncResult Model and Event Based Model methods into your proxy classes (there is no way to tell it to just generate the Event Based Model methods):

AddService2

The generated proxy will contain the following items for use with the Event Based Model:

  1. MyOperationCompletedEventArgs: For every operation, an event args class will be created which is used to return arguments from the MyOperationCompletedEvent.  These classes derive from System.ComponentModel.AsyncCompletedEventArgs and contain the value that is returned by the operation.
  2. MyOperationCompleted Event: For every operation, an event is created on the proxy when returns the event args for the operation.  Subscribe to this event to get the results of an asynchronous operation that uses the Event Based Model.
  3. MyOperationAsync methods:  For every operation, two new methods (one method is an override of the other) are created which always return void and whose names are the operation name with “Async” appended at the end.  These are the actual methods that are used to make the asynchronous calls in the Event Based Model.  The result of these methods will be returned via the MyOperationCompleted Event.  The first method generated has the same parameters as the original method.  The second method generated adds an “object UserState” as the last parameter.  This UserState is used to identify the operation or to pass information about the operation.

There are other items added to the proxy code when selecting this option, but those are for the IAsyncResult Model which will be discussed in the next article in this series.

Note that every method in the service gets an Aync version when you generate the proxy through SvcUtil or in Visual Studio.  If you only want a select number of asynchronous methods, you could always manually remove the addition methods and EventArgs, or you could manually create your own classes and not rely on the generated proxies.  If you are going to hand code proxies, I recommend that you generate them first, and use that code as an example to build on.

You can download a complete sample of the code discussed in this article here: http://www.danrigsby.com/Files/Rigsby.EventBasedWcfAsyncOperation.zip

Posted in Wcf | 7 Comments »

Disposable Base Class

Posted by Dan Rigsby on 15th March 2008

trashcanMany classes are built that implement System.IDisposable, which is a good thing.  This pattern makes for a good design to clean up your objects and can be used by the using statement to easily dispose of your objects.  This article already assumes that you know the basics of the Dispose Pattern. However sometimes having just a Dispose() method isn’t always enough.  Many times you a combination of a Disposed event, a void Dispose(bool disposing) method for use by a deconstructor, a boolean flag to check if the object IsDisposed, and maybe a method to check if the object is disposed that can throw an exception.  Some "best practices" often dictate that you should be using some of these additional things.  You may be writing this logic over and over again for each class, or you might start with a basic IDisposable pattern and weeks later you decide to refactor it to add in something like the boolean flag for IsDisposed.

After facing these same issues for awhile, I decided to put together a simple Diposable base class with all of the recommended patterns for using Disposable.  Of course, this can’t always be used since you might already have a base class.  But many times a class will derive from IDisposable and nothing else.  This is just screaming for a Disposable base class that encapsulates this logic!  For classes that already have a base class, I also have a code snippet to include everything that’s in the base class.

Here are the features of the Disposable Base Class and Code Snippet:

  1. void Dispose() Method – This is just the standard Dispose method that is defined in the IDisposable interface.
  2. void Dispose(bool disposing) Method – This method is called from the Dispose() method passing in true.  Its called from the deconstructor using false.  This is the method that you should override in your parent class and check if disposing is true before disposing of managed code.  The reason for this is that the deconstructor would have already disposed of the managed code, so you shouldn’t try to do it again.  If the deconstrutor called this method, you should only dispose of unmanaged code.
  3. void CheckDisposed() Method – This method is marked protected and is used by the parent class to check if the object is disposed.  It will throw an ObjectDisposedException if necessary.
  4. bool IsDisposed Property – A simple property to check whether or not this object has been disposed yet.
  5. Disposed Event – This event is fired when the object has been disposed.

To use the base class, you just override the Dispose(bool disposing) method. An example of this base class in use could look like this:

public class MyClass : Disposable
{
    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            // Dispose any managed code here
        }

        // Dispose any unmanaged code here

        base.Dispose(disposing);
    }
}

 

Here is the base class:

using System;
using System.ComponentModel;

namespace Rigsby
{
    /// <summary>
    /// Represents a basic disposable class.
    /// </summary>
    public abstract class Disposable : IDisposable
    {
        #region Private Properties
        private bool m_IsDisposed = false;
        #endregion Private Properties

        #region Public Properties
        /// <summary>
        /// Gets a value indicating whether this instance is disposed.
        /// </summary>
        /// <value>
        ///     <c>true</c> if this instance is disposed; otherwise, <c>false</c>.
        /// </value>
        [Browsable(false)]
        public bool IsDisposed
        {
            get
            {
                return m_IsDisposed;
            }
        }
        #endregion Public Properties

        #region Constructors
        /// <summary>
        /// Initializes a new instance of the <see cref="Disposable"/> class.
        /// </summary>
        public Disposable()
        {
        }

        /// <summary>
        /// Releases unmanaged resources and performs other cleanup operations before the
        /// <see cref="Disposable"/> is reclaimed by garbage collection.
        /// </summary>
        ~Disposable()
        {
            Dispose(false);
        }
        #endregion Constructors

        #region IDisposable Members
        private event System.EventHandler m_Disposed;

        /// <summary>
        /// Occurs when this instance is disposed.
        /// </summary>
        public event System.EventHandler Disposed
        {
            add
            {
                m_Disposed += value;
            }
            remove
            {
                m_Disposed -= value;
            }
        }

        /// <summary>
        /// Releases unmanaged and - optionally - managed resources
        /// </summary>
        public void Dispose()
        {
            if (!m_IsDisposed)
            {
                this.Dispose(true);
                GC.SuppressFinalize(this);
            }
        }

        /// <summary>
        /// Releases unmanaged and - optionally - managed resources
        /// </summary>
        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
        protected virtual void Dispose(bool disposing)
        {
            try
            {
                if (disposing)
                {
                    EventHandler handler = m_Disposed;
                    if (handler != null)
                    {
                        handler(this, EventArgs.Empty);
                        handler = null;
                    }
                }
            }
            finally
            {
                m_IsDisposed = true;
            }
        }
        #endregion IDisposable Members

        /// <summary>
        ///    <para>
        ///        Checks if the instance has been disposed of, and if it has, throws an <see cref="ObjectDisposedException"/>; otherwise, does nothing.
        ///    </para>
        /// </summary>
        /// <exception cref="ObjectDisposedException">
        ///    The instance has been disposed of.
        ///    </exception>
        ///    <remarks>
        ///    <para>
        ///        Derived classes should call this method at the start of all methods and properties that should not be accessed after a call to <see cref="Dispose()"/>.
        ///    </para>
        /// </remarks>
        protected void CheckDisposed()
        {
            if (m_IsDisposed)
            {
                string typeName = GetType().FullName;

                // TODO: You might want to move the message string into a resource file
                throw new ObjectDisposedException(
                    typeName,
                    String.Format(System.Globalization.CultureInfo.InvariantCulture,
                        "Cannot access a disposed {0}.",
                        typeName));
            }
        }
    }
}

Here is the code snippet version, or download it here.  If you use the snippet, you will want to manually change your class to derive from the IDisposable interface, then add this snippet.

<?xml version="1.0" encoding="utf-8"?> <CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">   <CodeSnippet Format="1.0.0">     <Header>       <Title>IDisposable</Title>       <Shortcut>       </Shortcut>       <Description>Implements the IDisposable interface with additional best practices.</Description>       <Author>Dan Rigsby</Author>     </Header>     <Snippet>       <Code Language="csharp"><![CDATA[        #region IDisposable Members
        private bool m_IsDisposed = false;
        private event System.EventHandler m_Disposed;

        /// <summary>
        /// Gets a value indicating whether this instance is disposed.
        /// </summary>
        /// <value>
        ///     <c>true</c> if this instance is disposed; otherwise, <c>false</c>.
        /// </value>
        [System.ComponentModel.Browsable(false)]
        public bool IsDisposed
        {
            get
            {
                return m_IsDisposed;
            }
        }

        /// <summary>
        /// Occurs when this instance is disposed.
        /// </summary>
        public event System.EventHandler Disposed
        {
            add
            {
                m_Disposed += value;
            }
            remove
            {
                m_Disposed -= value;
            }
        }

        /// <summary>
        /// Releases unmanaged and - optionally - managed resources
        /// </summary>
        public void Dispose()
        {
            if (!m_IsDisposed)
            {
                this.Dispose(true);
                System.GC.SuppressFinalize(this);
            }
        }

        /// <summary>
        /// Releases unmanaged and - optionally - managed resources
        /// </summary>
        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
        protected virtual void Dispose(bool disposing)
        {
            try
            {
                if (disposing)
                {
                    System.EventHandler handler = m_Disposed;
                    if (handler != null)
                    {
                        handler(this, System.EventArgs.Empty);
                        handler = null;
                    }
                }
            }
            finally
            {
                m_IsDisposed = true;
            }
        }

        /// <summary>
        ///    <para>
        ///        Checks if the instance has been disposed of, and if it has, throws an <see cref="ObjectDisposedException"/>; otherwise, does nothing.
        ///    </para>
        /// </summary>
        /// <exception cref="System.ObjectDisposedException">
        ///    The instance has been disposed of.
        ///    </exception>
        ///    <remarks>
        ///    <para>
        ///        Derived classes should call this method at the start of all methods and properties that should not be accessed after a call to <see cref="Dispose()"/>.
        ///    </para>
        /// </remarks>
        protected void CheckDisposed()
        {
            if (m_IsDisposed)
            {
                string typeName = GetType().FullName;

                // TODO: You might want to move the message string into a resource file
                throw new System.ObjectDisposedException(
                    typeName,
                    String.Format(System.Globalization.CultureInfo.InvariantCulture,
                        "Cannot access a disposed {0}.",
                        typeName));
            }
        }
        #endregion IDisposable Members]]></Code>     </Snippet>   </CodeSnippet> </CodeSnippets>

kick it on DotNetKicks.com

Posted in .Net, Common Libraries | 1 Comment »

Generic Notify Property Change Controller

Posted by Dan Rigsby on 14th March 2008

This is another example of a class you could put into a common library.   Suppose I want to create a class that fires an event every time the value of a property changes.  I could implement such a class like this:

public class MyClass : INotifyPropertyChanged
{
    private string m_Text;
    public string Text
    {
        get { return m_Text; }
        set
        {
            if (m_Text != value)
            {
                m_Text = value;
                OnPropertyChanged("Text");
            }
        }
    }

    protected virtual void OnPropertyChanged(
        string propertyName)
    {
        PropertyChangedEventHandler handler = m_PropertyChanged;
        if (handler != null)
        {
            m_PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    #region INotifyPropertyChanged Members
    private event PropertyChangedEventHandler m_PropertyChanged;
    public event PropertyChangedEventHandler PropertyChanged
    {
        add { m_PropertyChanged += value; }
        remove { m_PropertyChanged -= value; }
    }
    #endregion INotifyPropertyChanged Members
}
 
If you have a large class library and a lot of properties, this can add up to a lot of code.  There is an easier way to do this at a very small cost of performance.  Ill show the code for the PropertyController class at the end of this post, but this is an example of what the above code could look like:
 
public class MyClass : INotifyPropertyChanged
{
    private PropertyController m_PropertyController
    private string m_Text;
    public string Text
    {
        get { return m_Text; }
        set { m_PropertyController.ChangeProperty("Text", value);
    }

    #region INotifyPropertyChanged Members
    public event PropertyChangedEventHandler PropertyChanged
    {
        add { m_PropertyController.PropertyChanged += value; }
        remove { m_PropertyController.PropertyChanged -= value; }
    }
    #endregion INotifyPropertyChanged Members
}

 

That is significantly less code and much cleaner.  Just, imagine if I had a class library with 30 classes.

You could also do this:

set { m_PropertyController.ChangeProperty("Text", value);

 

instead of:

set { m_PropertyController.ChangeProperty(value);

 

The cost of doing this is that the PropertyController has to look at the stack trace, but depending on what you are doing, this may be worth the cost.

The ChangeProperty method returns a boolean to indicate whether or not the value was changed.  So inside your property code you could react depending on the result.

Here is the complete PropertyController class.  Feel free to use it, modify it, ignore it, etc. You could even use this class and not even expose the PropertyChanged event, if you don’t need it.

public class PropertyController : INotifyPropertyChanged, IDisposable
{
    private Dictionary<string, PropertyInfo> m_Properties =
        new Dictionary<string, PropertyInfo>();

    public PropertyController()
    {
    }

    #region INotifyPropertyChanged Members
    private event PropertyChangedEventHandler m_PropertyChanged;

    public event PropertyChangedEventHandler PropertyChanged
    {
        add
        {
            m_PropertyChanged += value;
        }
        remove
        {
            m_PropertyChanged -= value;
        }
    }
    #endregion INotifyPropertyChanged Members

    protected PropertyInfo GetProperty(string propertyName)
    {
        if (!m_Properties.ContainsKey(propertyName))
        {
            m_Properties.Add(propertyName, this.GetType().GetProperty(propertyName));
        }

        return m_Properties[propertyName];
    }

    public virtual bool ChangeProperty(object newValue)
    {
        return ChangeProperty(new System.Diagnostics.StackTrace().GetFrame(1).GetMethod().Name, newValue);
    }

    public virtual bool ChangeProperty(string propertyName, object newValue)
    {
        System.Reflection.PropertyInfo property =
            GetProperty(propertyName);

        if (property.GetValue(this, null) != newValue)
        {
            property.SetValue(this, newValue, null);
            OnPropertyChanged(propertyName);

            return true;
        }

        return false;
    }

    public virtual void OnPropertyChanged(
        string propertyName)
    {
        PropertyChangedEventHandler handler = m_PropertyChanged;
        if (handler != null)
        {
            m_PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    #region IDisposable Members
    public void Dispose()
    {
        m_PropertyChanged = null;
    }
    #endregion IDisposable Members
}

Posted in .Net, Common Libraries | 2 Comments »

ThirstyDeveloper Podcast’s: "Blog you should know"

Posted by Dan Rigsby on 10th March 2008

ThirstyDeveloper_small I don’t know how many of you listen the the ThirstyDevloper, but it is a fairly new audio podcast show from Dave Bost and Larry Clarkin, are our local Microsoft developer and architecture evangelists. This show is centered around developers and primarily Microsoft technologies, but they can dive into anything that might be interesting to other developers.  They published their first show on November 13th, 2007 and as of today have already published 14 shows with quite a few more in post production.  The show overall is getting better and better.  A couple of the first episodes had some audio issues where it would be loud then soft, but they are getting the kinks worked out and the content is getting deeper and deeper.  I recommend that you check it out.

One of the segments on their show is call “Blog you should know”.  In it both Dave and Larry each pick a blog that they think the listeners should be reading and following.  In the their March 1st, 2008 episode entitled “The Thirsty Developer 14: SCRUM“, I was surprised to hear that www.danrigsby.com was named Larry’s pick!  Larry claimed that I was “a great guy” and that this blog was his pick because of the recent posts on Wcf.  Larry said it “has deep meaningful stuff on Wcf” and is his “favorite blog to follow on the Wcf topic”.  I don’t know if I live up to all of Larry’s comments, but I appreciate the honor!

Here is the link to the show post which contains a link to the podcast and a mention of this blog: http://thirstydeveloper.com/2008/03/01/TheThirstyDeveloper14SCRUM.aspx

Posted in Community | No Comments »

.Net EventHandlers – Best Practices

Posted by Dan Rigsby on 9th March 2008

One question that comes up a lot is, “How can I can clean up my event handlers in an object?”.  What are the best practices for cleaning up event handlers?  This is actually a pretty important question.  One of the number one reasons for memory drains in .Net is because event handlers aren’t removed.   For instance: if ObjectA is registered for an event on ObjectB and ObjectB goes out of scope and should be garbage collected, it can’t because ObjectA still has a reference to do it via the event handler.  Get into some complex circular patterns, and you are just eating memory.

In an ideal world every time an object registers for an event, it should remove it when that object is destroyed, but what happens when the object it is listening for events on should be destroyed?

One way I use to get around this, is to declare the event as private, then expose it through a public property with Add and Remove accessor methods like so:

private System.EventHandler m_MyEvent;  

public event System.EventHandler MyEvent
{
    add
    {
        m_MyEvent += value;
    }
    remove
    {
        m_MyEvent -= value;
    }
}

Then in your Dispose() method or in some other clean up method, you can set the private event to null to remove all subscriptions to the event.

public void Dispose()
{
    m_MyEvent = null;
}

By setting the private event to null, you are basically telling it to remove any events listening to it. So that there are no more references to the object, so it can be disposed cleaning. This is similar to getting the invocation list of the event and removing all of the delegates:

foreach(System.EventHandler e in MyEvent.GetInvocationList())
{
    MyEvent -= e;
}

You could also use WeakReference objects which can be used to bypass this same situation.  However, it does involve rewriting a good chuck of code, and take a bit of thought to decide where to put it and where not to.  Using the method above can work with a WeakReference as well.  The nice thing about the method above is that the object is cleaning itself up and doesn’t rely on the GC or something else to do its dirty work.

Posted in .Net | 1 Comment »