What you want to see on DotNetFunda.com ?
Go to DotNetFunda.com
Twitter TwitterLinkedIn
YouTubeGoogle
 Online : 16546 |  Welcome, Guest!   Register  Login
Home > Articles > .NET Framework > Weak references in .NET (Part II)

Weak references in .NET (Part II)

2 vote(s)
Rating: 4.5 out of 5
Article posted by Vishvvas on 7/12/2011 | Views: 3989 | Category: .NET Framework | Level: Advance | Points: 250 red flag


This is continutaion of earlier article on the same subject, delving into long weak references.

Introduction & backgound


We have seen fundamentals of weak reference in previous article http://www.dotnetfunda.com/articles/article1419-weak-references-in-net-.aspx and we saw a practical example of usage of weak reference. A little excerpt from the said article “A strong reference is a reference pointing to an object created by new operator and the object would reside in the memory as long as the reference is pointing to an object in turn it protects the referenced object from being collected by GC (garbage collector). A weak reference is a reference that doesn’t protect the referenced object from being collected which means the object referenced by weak reference is considered unreachable (or weakly reachable) and so may be collected at any time, more precisely when  more memory is in needed. Different languages like java, C#, VB.NET, Python, Perl, Lisp etc support this feature.”

Weak reference are useful for objects which would use a lot of memory and these objects can be recreated easily if they are collected by GC.

To establish a weak reference with an object, you create a WeakReference using the instance of the object to be tracked. One can specify ‘false’ in the constructor if short weak reference is to be used otherwise ‘true’ for long weak reference. One then set the Target property to that object and set the object to null.

Let’s delve more into world of weak references and learn about long and short weak reference.

Description


The target of short weak reference becomes null when it is reclaimed by GC. A long weak reference is retained after the object’s finalize method is called i.e. when generally IDisposable pattern is implemented for unmanaged objects like database connections or file handles. When object doesn’t have Finalize method then the short weak reference functionality is applied. Such weak reference is valid until target is collected which can happen anytime after finalizer is run. This we can see that no object is reclaimed by GC even calling GC.Collect(); in case of long weak reference as Targets finalize method haven’t been called.

Scenario: We have a class named Person and also we need images representing the image of the person. We know Image type implements IDisposable (http://msdn.microsoft.com/en-us/library/system.idisposable.aspx) and hence can be used for long weak reference. Now there would be thousands of records for person which is having associated images. Generally this can be showed in data-grids (grid-views) or tree views where in thumbnail of image can be displayed. Such thumbnail would be prepared from image (Image. GetThumbnailImage() method). As this display may not critical to application i.e. this may not be required at many places and not much of business logic depends on this image display, one could think of using weak reference and here we would be using long. In previous article we employed short weak references.


Example:

Examples are in C# and exercise is done as console application.

public class Person

    {

        public string FirstName { getset; }

        public string LastName { getset; }

        public int PersonId { getset; }

 

        public Person(string firstName, string lastName)

        {

            this.FirstName = firstName;

            this.LastName = lastName;

        }

        public  Person(string firstName,string lastName, int ID)

        {

            this.FirstName = firstName;

            this.LastName = lastName;

            this.PersonId = ID;

        }

        public  string  PersonName

        {

            getreturn FirstName + " " + LastName;}

        }

    }

 

A class meant for holding different objects of persons and images, we would treat it as cache.

/// <summary>

    /// The class to hold different objects of Person and behave as cache

    /// </summary>

public class ImageCache

 {

    int regenarationCount = 0;// Track the number of times an object is regenerated after collection by GC

        private string personName = string.Empty;

 

        static Dictionary<intWeakReference> _personsImageCache;// cache for imagedatas

        static Dictionary<intPerson> _personsCache;//cache for person objects

        public int Count  // Returns the number of items in the cache.

        {

            get { return _personsImageCache.Count; }

        }

        public int RegenerationCount // Returns the number of times an  object had to be regenerated.

        {

            get { return regenarationCount; }

        }

        public string PersonName

        {

            get { return personName; }

        }

        public Image this[int index]

        {

            get

            {

                personName = _personsCache[index].PersonName;

                // Obtain an instance of a data  object from the personcache of  of weak reference objects.

                Image imageData = _personsImageCache[index].Target as Image;

                if (imageData == null//If the object was reclaimed, so generate a new one.

                {

                    Console.WriteLine("Regenerate object at {0}: Yes", index);

                    imageData =  Image.FromFile("@C:\\Users\\Public\\Pictures\\Sample Pictures\\Desert.jpg");

                    regenarationCount++;

                }

                else // As Object is not reclaimed so can be obtained with the weak reference.

                {

                    Console.WriteLine("Regenerate object at {0}: No", index.ToString());

                }

                return imageData;

            }

             

        }

          public ImageCache(int count)

        {

            _personsImageCache = new Dictionary<intWeakReference>();

            _personsCache = new Dictionary<intPerson>();

            // Add data objects with a short weak reference to the cache.

            for (int i = 0; i < count; i++)

            {

                Person person = new Person(i.ToString(), i.ToString(), i);

                _personsCache.Add(person.PersonId, person);

                //Long weak reference

                _personsImageCache.Add(person.PersonId, newWeakReference(Image.FromFile("C:\\Users\\Public\\Pictures\\Sample Pictures\\Desert.jpg"), true));

            }

        }

    }

 

Console application


  static void Main(string[] args)// for long Weakreference demo

        {

            int cacheSize = 5;//define the cache size.  For demonstration purpose, its taken very small.

            Random random = new Random();

            ImageCache imageCache = new ImageCache(cacheSize);// Create the cache with defined size

            string  personName;

            System.Drawing.Image image;

            // GC.Collect() is to be commented for ouput I where in the objects from cache are not collected by GC

            //and uncommented for output II

            Console.WriteLine("Demonstration of Long weak reference");

            Console.WriteLine("In method Main (...), the call to GC.Collect() is commented.");

             //GC.Collect();

            Console.WriteLine("***************Random Display of objects.***************");

            for (int i = 0; i < imageCache.Count; i++)

            {

                int index = random.Next(imageCache.Count);// Randomly access objects in the cache

                image = imageCache[index]; // Access the object by getting a property value

             //   Console.WriteLine("ImageData Name: " + image.Height.ToString());

                personName = imageCache.PersonName;

                Console.WriteLine("Person Name: " + personName);

            }

 

            double regenPercent = (((imageCache.RegenerationCount) * (100)) / (imageCache.Count));

            Console.WriteLine("Cache size: {0}, Regenerated: {1}%", imageCache.Count.ToString(), regenPercent.ToString());

            Console.WriteLine("***************************************************************");

            Console.ReadLine();

        }


Output: Two kinds of output are displayed.

I: GC not collecting the weak references as GC.Collect() is commented

Demonstration of Long weak reference

In method Main (...), the call to GC.Collect() is commented.

***************Random Display of objects.***************

Regenerate object at 4: No

Person Name: 4 4

Regenerate object at 4: No

Person Name: 4 4

Regenerate object at 1: No

Person Name: 1 1

Regenerate object at 3: No

Person Name: 3 3

Regenerate object at 3: No

Person Name: 3 3

Cache size: 5, Regenerated: 0%

***************************************************************

II: GC not collecting the weak references as they are long weak reference and application has gained the strong references

Demonstration of Long weak reference

In method Main (...), the call to GC.Collect() is uncommented.

***************Random Display of objects.***************

Regenerate object at 4: No

Person Name: 4 4

Regenerate object at 4: No

Person Name: 4 4

Regenerate object at 1: No

Person Name: 1 1

Regenerate object at 2: No

Person Name: 2 2

Regenerate object at 4: No

Person Name: 4 4

Cache size: 5, Regenerated: 0%

***************************************************************

Summary & Conclusion


The output clearly demonstrates what happens when one uses the long weak references. The weakly referenced objects are collected by GC (here is specifically called upon for demo but in practical scenarios when needed GC would collect these objects) when they are short weak reference and in case of long weak reference, it is retained even after the object’s Finalize method is called. So there are no regenerations occurred as the application has regained a strong reference to it. One needs to use property “Target” for using weak reference.

  • Use long weak references only when necessary as the state of the object is unpredictable after finalization.
  • Avoid using weak references to small objects because the pointer itself may be as large or larger.
  • Weak references shouldn’t be seen as an automatic solution to memory management problems. Instead, effective caching policy for handling your application's objects could help in better memory management

References:

If you like this article, subscribe to our RSS Feed. You can also subscribe via email to our Interview Questions, Codes and Forums section.

Page copy protected against web site content infringement by Copyscape
Found interesting? Add this to:



Please Sign In to vote for this post.

Experience:18 year(s)
Home page:http://www.dotnetfunda.com
Member since:Monday, May 30, 2011
Level:Bronze
Status: [Member]
Biography:Over 16 years of experience, worked across different technologies and programming languages like PB,VB, ASP. C++, C#, VB.NET
 Responses
Posted by: Naimishforu | Posted on: 15 Jul 2011 04:19:01 AM | Points: 25

I was looking for the first part of it. it's very nice...reading part 2 :)

>> Write Response - Respond to this post and get points
Related Posts

This is next write-up in the multipart series for SQL Server Integration with CLR aka SQL CLR and discusses the creation of SQL server trigger through SQL CLR.

The purpose of this article is to describe some of the practical uses of the Reflection.

This article describes how to create XML file and also shows various ways of reading XML File in .NET using XmlTextReader, XmlDocumenet, XPathDocument, DataSet and XmlDataSource control.

In this post I teach you how to read csv file using linq and imports its data in table

This article discusses the feature of integrating the CLR (Common Language Runtime) into the SQL server. This is first write-up of multi-part series on this subject and is mostly an excerpt from referenced article/s.

More ...
About Us | Contact Us | The Team | Advertise | Software Development | Write for us | Testimonials | Privacy Policy | Terms of Use | Link Exchange | Members | Go Top
General Notice: If you find plagiarised (copied) contents on this page, please let us know the original source along with your correct email id (to communicate) for further action.
Copyright © DotNetFunda.Com. All Rights Reserved. Copying or mimicking the site design and layout is prohibited. Logos, company names used here if any are only for reference purposes and they may be respective owner's right or trademarks. | 5/24/2013 4:57:19 PM