Category Archives: How to

Quartz – scheduling tasks in C#

Quartz is a scheduling library. You can run your task periodically.
This is how scheduler and it’s triggers can be configured.

        private static void ConfigureScheduler()
        {
            var scheduler = new StdSchedulerFactory().GetScheduler();
            var job = JobBuilder.Create<PrintDateTimeJob>()
                .WithIdentity("MyJob")
                .Build();

            var trigger = TriggerBuilder.Create()
                .StartAt(new DateTimeOffset(2000, 1, 1, 10, 0, 0, TimeSpan.FromSeconds(0)))
                .WithSimpleSchedule(x => x.WithIntervalInSeconds(5).RepeatForever())
                .WithIdentity("MyTrigger")
                .Build();

            scheduler.ScheduleJob(job, trigger);

            scheduler.Start();
        }

Your task class must implement IJob interface.

    class PrintDateTimeJob : IJob
    {
        public void Execute(IJobExecutionContext context)
        {
            Console.WriteLine("Current date and time: " + DateTime.Now.ToLongTimeString());
        }
    }

Code above will schedule simple job (printing current time) every 5 seconds. This is a simple example only. For detailed information go to: Quartz.NET.

C# – XML Serialization

This exaple shows how to serialize class to XML. XmlSerializer is used. Notice how attributes are used to avoid exceptions and format the output file.

namespace SimpleExamples
{
    static class SerializationIssue
    {
        public static void Serialize()
        {
            var config = new Config();
            config.Person1 = new People.Mx.Person() { Name = "John", BirthYear = 2000, Profession="SalesManager" };
            config.Person2 = new People.Ax.Person() { Name = "Adam", BirthYear = 1950, Profession="SoftwareDeveloper" };

            var path = Path.GetTempFileName();
            using (var s = new FileStream(path, FileMode.Create))
            {
                new XmlSerializer(typeof(Config)).Serialize(s, config);

                Console.WriteLine(s.Length);
                Process.Start(path);
            }

            var reader = File.OpenRead(path);
            var deserializedConfig = new XmlSerializer(typeof(Config)).Deserialize(reader) as Config;
        }
    }

    [Serializable]
    //sets namespace and name of the root element
    [XmlRoot(ElementName ="Configuration", Namespace ="Configurations")] 
    public class Config
    {
        [XmlElement(ElementName ="PersonA")] //sets the name of Person1 element
        public People.Mx.Person Person1 { get; set; }

        [XmlElement(ElementName ="PersonB")] //sets the name of Person1 element
        public People.Ax.Person Person2 { get; set; }

        [XmlIgnore] //this element won't be serialized
        public int X { get; set; }
    }
}

namespace People.Mx
{
    [Serializable]
    //allows to serialize many classes with the same name but in different namespaces
    //without this attribute on both Person classes exception is thrown during serialization
    [XmlType(TypeName = "Prsn1")] 
    public class Person : PersonBase
    {
        public string Profession { get; set; }
    }
}

namespace People.Ax
{
    [Serializable]
    //allows to serialize many classes with the same name but in different namespaces
    //without this attribute on both Person classes 
    //exception is thrown during serialization[XmlType(TypeName = "Prsn1")] 
    [XmlType(TypeName = "Prsn2")]
    public class Person : PersonBase
    {
        public string Profession { get; set; }
    }
}

namespace People.Base
{
    public class PersonBase
    {
        public string Name { get; set; }
        public int BirthYear { get; set; }
    }
}

For more about Equals method see:
https://msdn.microsoft.com/en-us/library/182eeyhh(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/58a18dwa(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/2baksw0z(v=vs.110).aspx

CodeDom – generate code dynamically

CodeDom is a feature which allows you to create code dynamically.
It means, you can define an object (System.CodeDom.CodeCompileUnit) which describes a new type to be created. Then you can print out prepared schema to file with c# code.
This sample shows how to prepare CodeCompileUnit for new class ‘Person’ and how to write code file with this class.

    class Program
    {
        static void Main(string[] args)
        {
            var template = CreateCodeTemplate("Person", 
                                        new Tuple<Type, string>(typeof(int), "Age"), 
                                        new Tuple<Type, string>(typeof(string), "Name"));
            var generatedFileName = GenerateCode(template);
            Console.WriteLine(generatedFileName);
            Console.ReadLine();
        }

        /// <summary>
        /// Creates schema of the code you want to generate. 
        /// Schema will contain class with given name and properties.
        /// </summary>
        /// <returns></returns>
        public static CodeCompileUnit CreateCodeTemplate(string className, params Tuple<Type, string>[] properties)
        {
            var mySample = new CodeCompileUnit();

            var myNamespace = new CodeNamespace("ExternalTool.Base");
            myNamespace.Imports.Add(new CodeNamespaceImport("System.Linq"));

            var myClass = new CodeTypeDeclaration(className);
            myClass.IsClass = true;
            myClass.Comments.Add(new CodeCommentStatement("Use this autogenerated class to create specific items."));

            foreach (var p in properties)
            {
                var privateMember = new CodeMemberField(typeof(int), "_" + p.Item2);

                var prop = new CodeMemberProperty();
                prop.Name = p.Item2;
                prop.Type = new CodeTypeReference(typeof(int));
                prop.GetStatements.Add(new CodeMethodReturnStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), privateMember.Name)));
                prop.SetStatements.Add(new CodeAssignStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), privateMember.Name), new CodePropertySetValueReferenceExpression()));

                myClass.Members.Add(privateMember);
                myClass.Members.Add(prop);
            }

            mySample.Namespaces.Add(myNamespace);
            myNamespace.Types.Add(myClass);

            return mySample;
        }

        /// <summary>
        /// Creates file with the C# code. Path to the created file is returned.
        /// </summary>
        /// <param name="template"></param>
        /// <returns></returns>
        public static string GenerateCode(CodeCompileUnit template)
        {
            var codeProvider = new CSharpCodeProvider();
            var fileName = Path.GetTempFileName();
            using (var writer = new StreamWriter(fileName, false))
            {
                var itWriter = new IndentedTextWriter(writer, "  ");// writes text with given tabbing
                codeProvider.GenerateCodeFromCompileUnit(template, itWriter, new CodeGeneratorOptions());
            }

            return fileName;
        }
    }

When the code above is started, file like this is generated:

//------------------------------------------------------------------------------
// <auto-generated>
//     Ten kod został wygenerowany przez narzędzie.
//     Wersja wykonawcza:4.0.30319.42000
//
//     Zmiany w tym pliku mogą spowodować nieprawidłowe zachowanie i zostaną utracone, jeśli
//     kod zostanie ponownie wygenerowany.
// </auto-generated>
//------------------------------------------------------------------------------

namespace ExternalTool.Base
{
    using System.Linq;


    // Use this autogenerated class to create specific items.
    public class Person
    {

        private int _Age;

        private int _Name;

        private int Age
        {
            get
            {
                return this._Age;
            }
            set
            {
                this._Age = value;
            }
        }

        private int Name
        {
            get
            {
                return this._Name;
            }
            set
            {
                this._Name = value;
            }
        }
    }
}

Activator

Activator allows you to create instance of an object when class name is unknown in compile time. It can be useful while creating plugins, reading data from external sources (like XML), etc.

See the example below. I have a ‘Person’ class in ‘Common’ library. Person class has got public parameterless constructor.
I can instantiate object of this class from another library (i.e. unit test) passing name of the dll and class (with namespace) in strings to Activator.
Notice: You must reference Microsoft.CSharp library to use ‘dynamic’ keyword.

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Windows;

namespace AnyTest
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Windows;

namespace AnyTest
{
    [TestClass]
    public class ActivatorTests
    {
        [TestMethod]
        public void TestMethod1()
        {
            dynamic myPerson = Activator.CreateInstance("Common", "Common.Person").Unwrap();
            Assert.IsTrue(myPerson.Age == 0);
        }
    }
}

Reading XML file

To read XML we can use XmlReader class. XmlReader read lines of xml file one by one.
Imagine we have following XML file:

<?xml version="1.0"?>
<catalog>
  <book id="bk101">
    <author>Gambardella, Matthew</author>
    <title>XML Developer's Guide</title>
    <genre>Computer</genre>
    <price>44.95</price>
    <publish_date>2000-10-01</publish_date>
    <description>
      An in-depth look at creating applications
      with XML.
    </description>
  </book>
  <book id="bk102">
    <author>Ralls, Kim</author>
    <title>Midnight Rain</title>
    <genre>Fantasy</genre>
    <price>5.95</price>
    <publish_date>2000-12-16</publish_date>
    <description>
      A former architect battles corporate zombies,
      an evil sorceress, and her own childhood to become queen
      of the world.
    </description>
  </book>
  <book id="bk103">
    <author>Corets, Eva</author>
    <title>Maeve Ascendant</title>
    <genre>Fantasy</genre>
    <price>5.95</price>
    <publish_date>2000-11-17</publish_date>
    <description>
      After the collapse of a nanotechnology
      society in England, the young survivors lay the
      foundation for a new society.
    </description>
  </book>
</catalog>

We can parse it in the following way:

        static void Read(string path)
        {
            XmlReader reader = XmlReader.Create(path);
            while (reader.Read()) //read the next line of the XML file
            {
                if (reader.Name == "catalog") //checks whether current item name is catalog (i.e. (<catalog>)
                {
                    if (reader.NodeType == XmlNodeType.Element) //checks whether current item is an element (i.e. <book>)
                        Console.WriteLine("Reading catalog started.");
                    if (reader.NodeType == XmlNodeType.EndElement) // check whether current item is an end of element (i.e. </book>)
                        Console.WriteLine("Reading catalog finished.");
                }
                if (reader.Name == "book")
                {
                    if (reader.NodeType == XmlNodeType.Element)
                    {
                        Console.WriteLine("Reading book started.");
                        if (reader.HasAttributes)
                        {
                            var idAttribute = reader["id"]; //tries to read attribute (i.e. <book id=123>)
                            Console.WriteLine($"Id attribute is: {idAttribute}");
                            var firstAttribute = reader[0]; //tries to read first attribute of the element (in this case returns the same as reader["id"])
                            Console.WriteLine($"First attribute is: {firstAttribute}");
                            var secondAttribute = reader["abc"]; //tries to read abc attribute (which doesn't exist) of the element (in this case returns null)
                            Console.WriteLine($"Second attribute is: {secondAttribute}");
                        }
                    }
                    if (reader.NodeType == XmlNodeType.EndElement)
                        Console.WriteLine("Reading book finished.");
                }

                if (reader.Name == "title" && reader.NodeType == XmlNodeType.Element)
                {
                    var titleWithTags = reader.ReadOuterXml(); // reads title with tags
                    Console.WriteLine($"Title (with tags) is: {titleWithTags}");
                }

                if (reader.Name == "description" && reader.NodeType == XmlNodeType.Element)
                {
                    var description = reader.ReadInnerXml(); //reads the content of the <description> element
                    Console.WriteLine($"Description is: {description}");
                }

                if (reader.Name == "price" && reader.NodeType == XmlNodeType.Element)
                {
                    var price = reader.ReadElementContentAs(typeof(decimal), null);
                    Console.WriteLine($"Parsed price is: {price}");
                }
            }
        }

There is also second option – LINQ to XML. We can parse mentioned document like this:

        static void ReadByLinq(string path)
        {
            XDocument doc = XDocument.Load(path);
            var books = doc.Descendants().Where(x => x.NodeType == XmlNodeType.Element && x.Name == "book").ToList();
            Console.WriteLine($"There are {books.Count} books:");
            foreach (var b in books)
            {
                Console.WriteLine("Id attribute is: " + b.Attributes().FirstOrDefault(x => x.Name == "id").Value);
                Console.WriteLine("Title is: " + b.Elements().FirstOrDefault(x => x.NodeType == XmlNodeType.Element && x.Name == "title").Value);
            }
        }

Be aware of the fact that the second option loads the whole file into memory!

Mutex – synchronizing processes

Mutex is a mechanism which allows us to synchronize processes. (see also: semaphore).
Mutex is resource consuming stuff, so avoid it if possible.

Imagine we have an application which writes something into a file. If we run two instances lines in file will be mixed.

        public void WriteToSharedFileWithoutSync()
        {
            StreamWriter oFile = null;
            try
            {
                for (int i = 0; i <= 25; i++)
                {
                    oFile = File.AppendText(@"logger.log");
                    var txt = "Sample line..." + i;
                    oFile.WriteLine(txt);
                    Console.WriteLine(txt);
                    oFile.Flush();
                    oFile.Close();
                    Thread.Sleep(250);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
            finally
            {
                if (null != oFile)
                {
                    oFile.Close();
                    oFile.Dispose();
                }

                Console.Write("Saving finished.");
            }
        }

Run code above executing two separate instances of the same application to see results.

We can synchronize this two instances using mutex. See example below.

        private Mutex _mutex = new Mutex(false, "991FE2BE-A4DD-47CE-AC9B-C97A908EA560"); //create mutex with unique name somewhere in your application 


        public void WriteToSharedFileWithSync()
        {
            _mutex.WaitOne(); //wait if somebody else is in critical section

            StreamWriter oFile = null;
            try
            {
                for (int i = 0; i <= 25; i++)
                {
                    oFile = File.AppendText(@"logger.log");
                    var txt = "Sample line..." + i;
                    oFile.WriteLine(txt);
                    Console.WriteLine(txt);
                    oFile.Flush();
                    oFile.Close();
                    Thread.Sleep(250);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
            finally
            {
                if (null != oFile)
                {
                    oFile.Close();
                    oFile.Dispose();
                }

                _mutex.ReleaseMutex(); //release critical section after writing
                Console.Write("Saving finished.");
            }
        }

Semaphore – synchronizing threads and processes

Semaphore is a mechanism similar to mutex and lock, but there are a few differences:
a) Semaphore can allow more than one thread to access critical section.
b) Semaphore can synchronize processes.

Imagine we have four threads. Every one writes a text A, B, C or D one hundred times.

        public void StartWithoutSynchronization()
        {
            //this task prints A
            var taskA = new Task(() =>
            {
                for (int i = 0; i < 100; i++)
                {
                    Console.WriteLine("A " + i);
                }
            });

            //this task prints A
            var taskB = new Task(() =>
            {
                for (int i = 0; i < 100; i++)
                {
                    Console.WriteLine("B " + i);
                }
            });

            //this task prints A
            var taskC = new Task(() =>
            {
                for (int i = 0; i < 100; i++)
                {
                    Console.WriteLine("C " + i);
                }
            });

            //this task prints A
            var taskD = new Task(() =>
            {
                for (int i = 0; i < 100; i++)
                {
                    Console.WriteLine("D " + i);
                }
            });

            taskA.Start();
            taskB.Start();
            taskC.Start();
            taskD.Start();
            Task.WaitAll(taskA, taskB, taskC, taskD);

            Console.WriteLine("Finished");
        }

If we run this code all thread will work simultaneously as there is no synchronization.
Now imagine we want to have only two threads working at a time. We can do it with semaphore.
Synchronizing threads:

        public void StartSynchronizedWithSemaphore()
        {
            var semaphore = new Semaphore(2, 2); // initialized to allow two thread at a time from beginning to the end

            //this task prints A
            var taskA = new Task(() =>
            {
                semaphore.WaitOne(); // waits if blocked; if can go - it decreases counter in semaphore
                for (int i = 0; i < 100; i++)
                {
                    Console.WriteLine("A " + i);
                }
                semaphore.Release(); // releases semaphore - counter is increased
            });

            //this task prints A
            var taskB = new Task(() =>
            {
                semaphore.WaitOne();
                for (int i = 0; i < 100; i++)
                {
                    Console.WriteLine("B " + i);
                }
                semaphore.Release();
            });

            //this task prints A
            var taskC = new Task(() =>
            {
                semaphore.WaitOne();
                for (int i = 0; i < 100; i++)
                {
                    Console.WriteLine("C " + i);
                }
                semaphore.Release();
            });

            //this task prints A
            var taskD = new Task(() =>
            {
                semaphore.WaitOne();
                for (int i = 0; i < 100; i++)
                {
                    Console.WriteLine("D " + i);
                }
                semaphore.Release();
            });

            taskA.Start();
            taskB.Start();
            taskC.Start();
            taskD.Start();
            Task.WaitAll(taskA, taskB, taskC, taskD);

            Console.WriteLine("Finished");
        }

When you run this code you will see that only two threads are running. The next one thread starts only when one of the previous threads is finished.

Synchronizing processes
Imagine new situation. We have an application and we want maximally two application instances processing at a time. We can initialize a semaphore with a name – it will work for all processes. We create an application with single method in it:

        public void StartSynchronizedProcessWithSemaphore()
        {
            //when name is passed into constructor - you synchronize processes
            var semaphore = new Semaphore(2, 2, "SemaphoreDemoApp"); 

            semaphore.WaitOne();
            Console.WriteLine("Application is processing... " + DateTime.Now.ToLongTimeString());
            Thread.Sleep(TimeSpan.FromSeconds(15));
            Console.WriteLine("Application stops processing... " + DateTime.Now.ToLongTimeString());
            semaphore.Release();
        }

Now we can compile and run the same application i.e. four times. You will notice that only in two windows you will see that application is processing. Until this two are not finished, any other is started.