Dan Rigsby - Coding Up Style

.Net, C#, & Wcf Development

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

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 | 3 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

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 | 5 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

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 t