Wednesday 6 April 2016

How to run a long running Task in Windows Forms with out Freeze the UI

In this post we are going to see how to run a long running task in windows forms with out freezing a UI, Generally if we do any long running operation in a Button click results in Freeze of UI, this is because of UI thread is running with some long running task so busy, now how we can make the Winforms to run a long running task with out Freeze UI..

To do this we have a create a separate thread which is running background from the Main UI thread, we can easily did that by BackgroundWorker class, and also can report the status to the UI.

Let we drag and drop two text box and two labels,  1 progress bar , 1 backgroundworker




Code
**************

    public partial class Calculation : Form
    {
        public Calculation()
        {
            InitializeComponent();
            calcWorker.WorkerReportsProgress = true;
            calcWorker.ProgressChanged += CalcWorker_ProgressChanged;
            calcWorker.DoWork += CalcWorker_DoWork;
            calcWorker.RunWorkerCompleted += CalcWorker_RunWorkerCompleted;
        }

        private void CalcWorker_RunWorkerCompleted(object sender, 
                RunWorkerCompletedEventArgs e)
        {
            button1.Enabled = true;
        }

        private void CalcWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            CalcParams param = e.Argument as CalcParams;

            for (int i = 0; i < 5; i++)
            {
                System.Threading.Thread.Sleep(2000);
                calcWorker.ReportProgress(20 * i);
            }

            int result = param.Num1 + param.Num2;
            calcWorker.ReportProgress(100, result);
        }

        private void CalcWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            progressBar1.Value = e.ProgressPercentage;

            if(e.ProgressPercentage == 100)
            {
                MessageBox.Show(e.UserState.ToString());
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            
             CalcParams param = new CalcParams() { 
                         Num1 =Convert.ToInt32( textBox1.Text), 
                         Num2 = Convert.ToInt32( textBox2.Text)
              };

            calcWorker.RunWorkerAsync(param);
            button1.Enabled = false;

        }
    }


    public class CalcParams
    {
        public int Num1 { setget; }

        public int Num2 { setget; }
    }


output:
***************






From this post you can see how to do a long running task in windows forms with out freezing UI.

Sunday 3 April 2016

Create a custom configuration section in web.config or in app.config file using C#

In this post we are going to see how to create a custom configuration section in web.config file or app.config file using c#, for that first we have to decide what kind of format that xml will going to look like , then only we can create element based on that, now for this post let we see , what kind of format we are trying to achieve.

Configuration are used to give the values for software during runtime. below is the structure we are going to build now.


<ComConfig name="development">
      <Companies>
        <Company name="Microsoft">
          <Address street="RF street" city="Manhat" state="NYC" country="US" />
          <Projects>
            <Project name="C#">
              <Developers>
                <Developer name="Rajesh" designation="Architect" />
                <Developer name="Suresh" designation="Tech Lead" />
              </Developers>
            </Project>
            <Project name="VisualStudio">
              <Developers>
                <Developer name="Ramu" designation="Senior Developer" />
                <Developer name="Appu" designation="Project Lead" />
              </Developers>
            </Project>
          </Projects>
        </Company>
        <Company name="Google">
          <Address street="GH street" city="Ledts" state="Pollis" country="US" />
          <Projects>
            <Project name="Android">
              <Developers>
                <Developer name="Chris" designation="Architect" />
                <Developer name="Xing" designation="Project Lead" />
              </Developers>
            </Project>
            <Project name="gmail">
              <Developers>
                <Developer name="Xander" designation="Senior Developer" />
                <Developer name="Palo" designation="Tech Lead" />
              </Developers>
            </Project>
          </Projects>
        </Company>
      </Companies>
    </ComConfig>

from the above structure you can see lot of elements are there, some of them are collections, some of them are attributes.
For create a custom configuration element we need to derive the class from the ConfigurationElement and we have to define the property with ConfigurationProperty attribute.


 public class CompanyElement : System.Configuration.ConfigurationElement
 {
        [ConfigurationProperty("name", IsRequired = true)]
        public string Name
        {
            get { return (string)base["name"]; }
        }
 }

For define the customElement collection , we are defining a generic class, instead of creating collection class for each and every element , we are creating a generic class

Generic element collection:


public class ConfigurationElementCollection<T> : ConfigurationElementCollection     
  IEnumerable<Twhere T : ConfigurationElementnew()
    {
        List<T> _elementCollection = new List<T>();

        protected override ConfigurationElement CreateNewElement()
        {
            T elem = new T();
            _elementCollection.Add(elem);
            return elem;
        }

        protected override object GetElementKey(ConfigurationElement element)
        {
            return _elementCollection.Find(x => x.Equals(element));
        }

        public T this[int index]
        {
            get
            {
                T ele = default(T);
                if (index < _elementCollection.Count)
                {
                    ele = _elementCollection[index];
                }
                return ele;
            }
        }
        
        IEnumerator<TIEnumerable<T>.GetEnumerator()
        {
            return _elementCollection.GetEnumerator();
        }
    }



How to use:

       [ConfigurationProperty("Developers",IsRequired =true)]
       [ConfigurationCollection(typeof(DeveloperElement),AddItemName ="Developer",
             RemoveItemName ="RemoveDeveloper",ClearItemsName ="ClearDeveloper")]
       public ConfigurationElementCollection<DeveloperElement> Developers
        {
            get
            {
                return (ConfigurationElementCollection<DeveloperElement>)base["Developers"];
            }

        }


Above is sample how we have to declare the collection of an element
Here we have to create element for the four elements :- Company, Address, Project, Developer
Element Collection : Companies, Projects, Developers using Generic one
ConfigurationManager : ConfigurationSection
Next step is Declaration of configuration section in Configuration file, then add the configuration

Now let we see the implementation of each and every part one by one : first let we create each and every element finally we will creation section.

DeveloperElement


    public class DeveloperElement:ConfigurationElement
    {
        [ConfigurationProperty("name",IsRequired =true)]
        public string Name
        {
            get { return (string)base["name"]; }
        }

        [ConfigurationProperty("designation",IsRequired =true)]
        public string Designation
        {
            get { return (string)base["designation"]; }
        }

    }





 ProjectElement 

    public class ProjectElement : ConfigurationElement
    {    
        [ConfigurationProperty("name",IsRequired =true)]
        public string Name
        {
            get
            {
                return (String)base["name"];
            }
        }    


       [ConfigurationProperty("Developers",IsRequired =true)]
       [ConfigurationCollection(typeof(DeveloperElement),AddItemName ="Developer",
             RemoveItemName ="RemoveDeveloper",ClearItemsName ="ClearDeveloper")]
       public ConfigurationElementCollection<DeveloperElement> Developers
        {
            get
            {
                return (ConfigurationElementCollection<DeveloperElement>)base["Developers"];
            }
        }
    }


AddressElement 


    public class AddressElement : ConfigurationElement
    {
        [ConfigurationProperty("street", IsRequired = true)]
        public string street
        {
            get { return (string)base["street"]; }
        }

        [ConfigurationProperty("city", IsRequired = true)]
        public string city
        {
            get { return (string)base["city"]; }
        }

        [ConfigurationProperty("state", IsRequired = true)]
        public string state
        {
            get { return (string)base["state"]; }
        }

        [ConfigurationProperty("country", IsRequired = true)]
        public string country
        {
            get { return (string)base["country"]; }
        }
    }



 CompanyElement 

    public class CompanyElement : ConfigurationElement
    {
        [ConfigurationProperty("name", IsRequired = true)]
        public string Name
        {
            get { return (string)base["name"]; }
        }

        [ConfigurationProperty("Address", IsRequired = true)]
        public AddressElement Address
        {
            get { return (AddressElement)base["Address"]; }
        }

        [ConfigurationProperty("Projects",IsRequired =true)]
        [ConfigurationCollection(typeof(ProjectElement),AddItemName ="Project",
        ClearItemsName ="ClearProject",RemoveItemName ="RemoveProject")]
        public ConfigurationElementCollection<ProjectElement> Projects
        {
            get
            {
                return (ConfigurationElementCollection<ProjectElement>)base["Projects"];
            }
        }


    }



Finally we will create configuration section

namespace COMConfig
{
    public class ConfigurationManager: System.Configuration.ConfigurationSection
    {
        public static ConfigurationManager settings = (ConfigurationManager)
             System.Configuration.ConfigurationManager.GetSection("ComConfig");

        public static ConfigurationManager AppSettings
        {
            get
            {
                return settings;
            }
        }

        [System.Configuration.ConfigurationProperty("name",IsRequired =true,IsKey =true)]
        public string Name
        {
            get
            {
                return (string)base["name"];
            }            
        }

        [System.Configuration.ConfigurationProperty("Companies", IsRequired = true)] 
        [System.Configuration.ConfigurationCollection(typeof(CompanyElement),
         AddItemName ="Company", ClearItemsName = "ClearCompany"
        RemoveItemName = "RemoveCompany")]       
        public ConfigurationElementCollection<CompanyElement> Companies
        {
            get
            {
                return (ConfigurationElementCollection<CompanyElement>)base["Companies"];
            }
        }

        
    }
   
}



Declaration of Section in configuration
The name which is declared in the name of the section should be the starting element, type should be specified along with namespace , assembly ... Give this info correctly , because  sometimes you may forget to mention the assembly name correctly for example here ConfigSample is assembly name

Note : whatever element you define in xml file must have element declaration in code.
<configSections>  
      <section name="ComConfig" type="COMConfig.ConfigurationManager, ConfigSample"/>  
  </configSections>

Full configuration File:


<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  
    <configSections>  
      <section name="ComConfig" type="COMConfig.ConfigurationManager, ConfigSample"/>  
  </configSections>
  
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6" />
  </startup>
  
  

    <ComConfig name="development">
      <Companies>
        <Company name="Microsoft">
          <Address street="RF street" city="Manhat" state="NYC" country="US" />
          <Projects>
            <Project name="C#">
              <Developers>
                <Developer name="Rajesh" designation="Architect" />
                <Developer name="Suresh" designation="Tech Lead" />
              </Developers>
            </Project>
            <Project name="VisualStudio">
              <Developers>
                <Developer name="Ramu" designation="Senior Developer" />
                <Developer name="Appu" designation="Project Lead" />
              </Developers>
            </Project>
          </Projects>
        </Company>
        <Company name="Google">
          <Address street="GH street" city="Ledts" state="Pollis" country="US" />
          <Projects>
            <Project name="Android">
              <Developers>
                <Developer name="Chris" designation="Architect" />
                <Developer name="Xing" designation="Project Lead" />
              </Developers>
            </Project>
            <Project name="gmail">
              <Developers>
                <Developer name="Xander" designation="Senior Developer" />
                <Developer name="Palo" designation="Tech Lead" />
              </Developers>
            </Project>
          </Projects>
        </Company>
      </Companies>
    </ComConfig>



</configuration>

How we are going to access the created configuration
Now see the code how we are going to access the values from this element.


           ConfigurationManager coll = ConfigurationManager.AppSettings;

            foreach (CompanyElement item in coll.Companies)
            {
                Console.WriteLine("\n");
                Console.WriteLine("\tCompany Name : " + item.Name);
                Console.WriteLine(string.Format("\tAddress {0}, {1}, {2}, {3}",
                   item.Address.street,item.Address.city,
                   item.Address.state,item.Address.country));

                foreach (ProjectElement proj in item.Projects)
                {
                    Console.WriteLine("\n");
                    Console.WriteLine("\t\tProject Name : " + proj.Name);

                    foreach (DeveloperElement dev in proj.Developers)
                    {
                        Console.WriteLine(string.Format("\t\t\tDeveloper Name : {0}, 
                         Designation {1}", dev.Name, dev.Designation));
                    }
                   
                }

                
            }

            Console.Read();

Output :









From this post you can see how to create a custom configuration section for App.config or Web.config using C#.