Monday 3 October 2016

Disposing objects instantiated by MEF

Experienced developers that has worked with the official extensibility framework in .NET, the Managed Extensibility Framework (MEF) allows the composition of different parts into more composite parts through composition. MEF has got similarities to other IoC framework, where you register components and then make use of them in other components. However, with MEF there is a caveat and an important one too!
MEF beautifully abstracts away the IoC container and lets you specify parts that can be epxorted and imported. But if you inspect your application or system with a memory profiler such as JetBrains DotMemory or Red Gate Memory Profiler, you soon find out that much of the memory used by your applications is not properly disposed, i.e freed up after use. This is the case for nonshared (non-singleton) objects that are exported and then instantiated (imported). This means that your application will through continued use hold more and more memory. It will leak memory. By inspecting the memory dependency chain, one can see that MEF is the reason why the nonshared objects instantiated by MEF is not released, even after the objects are issued to be disposed.

I use in this code the ServiceLocator found with the Enterprise Library. Make note that my code will break up the dependency chain that hinders the object, but it does not mean that necessarily objects will be disposed right away. After all, .NET is managed and decides itself when objects are really to be disposed. But if you strive with releasing objects that are tied to memory even after use and also use MEF, read on.

I use the Factory pattern here to instantiate objects. I also use the new feature in .NET 4.5 that is called the ExportLifeTimeContext. I also use the ExportFactory in MEF inside a class called ExportFactoryInstantiator that does actual instantiation of the objects and keeping a track of these ExportLifeTimeContext objects. As noted, you need at least .NET 4.5 to make this work. For .NET 4.0 users, sorry - you are out of luck as far as I know. Upgrade your application to .NET 4.5 if possible and get the newer version of MEF.

The code below shows how you can accomplish control over memory resources using MEF:

MefFactory.cs

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using Microsoft.Practices.ServiceLocation;

namespace SomeAcme.Client.Infrastructure.IoC
{

    /// <summary>
    /// Factory for MEF Parts that is able to actually dispose MEF instantiated objects and get around bug in MEF 
    /// where objects never gets properly GC-ed when they should dispose
    /// </summary>
    /// <typeparam name="T"></typeparam>
    [Export]
    [PartCreationPolicy(CreationPolicy.Shared)]
    public class MefFactory<T> : IPartImportsSatisfiedNotification 
    {

        /// <summary>
        /// Backlog that keeps track of mef parts that are instantiated via this factory 
        /// </summary>
        private static readonly ConcurrentBag<ExportLifetimeContext<T>> MefParts = new ConcurrentBag<ExportLifetimeContext<T>>();

        /// <summary>
        /// Disposes parts added to the mef factory backlog of type T
        /// </summary>
        public static void DisposeMefParts()
        {
            ExportLifetimeContext<T> item;
            while (MefParts.TryTake(out item))
            {
                if (item != null)
                    item.Dispose();
            }
        }

        /// <summary>
        /// Disposes parts added to the mef factory backlog of type T by a given predicate condition
        /// </summary>
        public static void DisposeMefParts(Predicate<T> condition)
        {
            ExportLifetimeContext<T> item;
            List<ExportLifetimeContext<T>> lifeTimeProlonged = new List<ExportLifetimeContext<T>>();
            while (MefParts.TryTake(out item))
            {
                if (item != null && condition(item.Value))
                    item.Dispose();
                else 
                    lifeTimeProlonged.Add(item);
            }
            if (lifeTimeProlonged.Any())
            {
                //Add back again the parts not matching condition to the Concurrent bag
                foreach (var part in lifeTimeProlonged)
                {
                    MefParts.Add(part);
                }
            }
        }

        public void OnImportsSatisfied()
        {
            //marker interface
        }
   
        /// <summary>
        /// Resolves the mef part
        /// </summary>
        /// <returns></returns>
        public static T Resolve()
        {
            var factoryInstantiator = ServiceLocator.Current.GetInstance<ExportFactoryInstantiator<T>>();
            MefParts.Add(factoryInstantiator.Lifetime);
            return factoryInstantiator.Instance;
        }

    }
}



using System.ComponentModel.Composition;

namespace SomeAcme.Client.Infrastructure.IoC
{

    [Export]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public class ExportFactoryInstantiator<T> : IPartImportsSatisfiedNotification
    {

        [Import]
        public ExportFactory<T> Factory { get; set; }

        public T Instance { get; private set; }

        private ExportLifetimeContext<T> _lifeTime;

        public ExportLifetimeContext<T> Lifetime
        {
            get { return _lifeTime; }
        } 

        public void OnImportsSatisfied()
        {
            _lifeTime = Factory.CreateExport();
            Instance = _lifeTime.Value;
        }

        public bool DisposeOnDemand()
        {
            if (_lifeTime == null)
                return false;
            _lifeTime.Dispose();
            return Instance == null;
        }

    }

}

To instantiate an object, you do:

 var somepart = MefFactory.Resolve();

When you are done using the object you can dispose it with:

 MefFactory.DisposeMefParts(); 

Please note, you can use a Predicate here to filter out which object you want to keep and which ones to dispose.

And once more, the immediate disposal of the object is not guaranteed, since GC will still control the true lifetime of objects. You can use GC.Collect(); to force releasing disposed objects, but that will usually degrade application performance.

But the techniques shown here will over time really improve your application by gaining control on the memory footprint your application uses.

Resources

[1] Enterprise Library: https://msdn.microsoft.com/library/cc467894.aspx
[2] ServiceLocator class: https://msdn.microsoft.com/en-us/library/microsoft.practices.servicelocation.servicelocator(v=pandp.51).aspx
[3] ServiceLocator pattern: https://msdn.microsoft.com/en-us/library/ff648968.aspx
[4] Managed Extensibility Framework: https://msdn.microsoft.com/en-us/library/dd460648(v=vs.110).aspx

Thursday 30 June 2016

Creating TPL Dataflow meshes to construct pipelines of computations

The TPL DataFlow Library allows the creation of simple and more complex data meshes that propagate data computations and exceptions using the Nuget package Microsoft.Tpl.DataFlow Let's look at how we can create a compound mesh to do three calculations that is considered as a single mesh. These simple examples appear to give simple computations as these a huge overhead in complexity. Of course, you would use Microsoft.Tpl.DataFlow for more complex scenarios, the simple example is just used for clarity. Consider the following code: First off, make sure you add a reference to Microsoft.Tpl.Dataflow, since TPL Dataflow is not part of the base class Library BCL in .NET. In the Nuget Package Explorer commandline in VS:
Install-Package Microsoft.Tpl.DataFlow

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Threading.Tasks.Dataflow;

namespace DataFlowDemo
{

    class Program
    {

        static void Main(string[] args)
        {
            //TplDataDemo();
            SecondTplDataDemo();
            Console.WriteLine("Press any key to continue ..");
            Console.ReadKey();
        }

        private static async void SecondTplDataDemo()
        {
            int[] nums = { 1, 13, 26, 14, 29, 15 };
            Console.WriteLine("Input numbers: ");
            foreach (var n in nums)
                Console.WriteLine(n);
            IPropagatorBlock<int, int> compountBlock = GetPropagatorBlock();
            Console.WriteLine("Pipeline: " + "x = (x * 2) => (x + 2) => (x / 2)");
            foreach (var num in nums)
            {
                compountBlock.Post(num);
            }
            try
            {

                while (true)
                {
                    try
                    {
                        Task<int> f = compountBlock.ReceiveAsync(TimeSpan.FromSeconds(1));
                        await f;
                        await Task.Delay(1000);
                        Console.WriteLine(f.Result);
                    }
                    catch (TimeoutException err)
                    {
                        //Console.WriteLine(err.Message);
                        break;
                    }
                    catch (Exception err)
                    {
                        //Console.WriteLine(err.Message);
                        throw err;
                    }
                }

            }
            catch (Exception err)
            {
                Console.WriteLine(err.Message);
            }
        }

        private static IPropagatorBlock<int, int> GetPropagatorBlock()
        {
            var multiplyBlock = new TransformBlock<int, int>(item => item * 2);
            var addBlock = new TransformBlock<int, int>(item => item + 2);
            var divideBlock = new TransformBlock<int, int>(item => item / 2);

            var flowCompletion = new DataflowLinkOptions { PropagateCompletion = true };
            multiplyBlock.LinkTo(addBlock, flowCompletion);
            addBlock.LinkTo(divideBlock, flowCompletion);

            return DataflowBlock.Encapsulate(multiplyBlock, divideBlock);
        }
  }

We build up the steps of the computation pipeline as a TransformBlock. The multiplyblock is linked to the addBlock and the divideBlock is then linked to the addBlock. We got a pipeline like this: multiplyBlock-addBlock-divideBlock. Each computation will then be: y = (x * 2) => z = y + 2 => w = z / 2. We also use the Encapsulate method to glue together the start step and the end step. We then get the following output:
Input numbers:
1
13
26
14
29
15
Pipeline: x = (x * 2) => (x + 2) => (x / 2)
2
14
27
15
30
16
Press any key to continue ..
Test out TPL Dataflow sample above (VS 2015 solution here: VS Solution With sample code above (.zip)

Wrapping Asynchronous Programming Model (APM) to Task-based Asynchronous Pattern (TAP)

Let's look at how we can wrap classic Begin and End methods used in APM to the newer Task-based Asynchronous Pattern (TAP). Many methods of older framework Versions of .NET support such APM methods and we want to wrap or adapt them to support TAP and async await. Example code:

using System;
using System.IO;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace ApmToTap
{
    class Program
    {

        static void Main(string[] args)
        {
            DownloadDemo();

            Console.WriteLine();
            Console.ReadKey();
        }

        private static async void DownloadDemo()
        {
            WebRequest wr = WebRequest.Create("https://t.co/UrkiLgN1BC");
            try
            {
                var response = await wr.GetResponseFromAsync();
                using (Stream stream = response.GetResponseStream())
                {
                    StreamReader reader = new StreamReader(stream, Encoding.UTF8);
                    Console.WriteLine(reader.ReadToEnd());
                }
            }
            catch (Exception err)
            {
                Console.WriteLine(err.Message);
            }
        }
    }

    public static class WebRequestExtensions
    {

        public static Task<WebResponse> GetResponseFromAsync(this WebRequest request)
        {
            return Task<WebResponse>.Factory.FromAsync(request.BeginGetResponse,
                request.EndGetResponse, null);
        }

    }

}

We use the Task<T>Factory.FromAsync method and provide the delegates for the Begin and End methods used in APM. We then provide just null as the AsyncState parameter, as this is not needed. We then can await the Task we create here and get the functionality Task provides such as information of how the asynchronous operation went, exceptions and so on. And of course we can also get the result we usually retrieve in the End method using APM. So there you have it. To use TAP With APM methods, you can use the Task<T>FromAsync method.