This is not a complete tutorial for C#. But the described topics are some essential feature of C# that is necessary for developing SCADA, OPC, ADS library, etc. 

See a complete Thread related example with explanations

Usages of Lock in Thread:

A thread is a small set of instructions designed to be scheduled and executed by the CPU independently of the parent process.

The lock keyword ensures that one thread does not enter a critical section of code while another thread is in the critical section. If another thread tries to enter a locked code, it will wait, block, until the object is released. This is also a synchronization mechanism in C#.

Usages of lock:

lock (x)
{
    // Your code that you want to protect (can be statement or expression)
}

In the following example, when a balance is being updated then other threads must wait.

namespace LockTestConsoleApplication
{
    public class Account
    {
        private readonly object balanceLock = new object();
        private decimal balance;
        public Account(decimal initialBalance)
        {
            balance = initialBalance;
        }
        public decimal Debit(decimal amount)
        {
            lock (balanceLock)
            {
                if (balance >= amount)
                {
                    Console.WriteLine("Balance before debit: {0}", balance);
                    Console.WriteLine("Amount to remove {0}", amount);
                    balance = balance - amount;
                    Console.WriteLine("Balance after debit  : {0}", balance);
                    return amount;
                }
                else
                {
                    return 0;
                }
            }
        }
        public void Credit(decimal amount)
        {
            lock (balanceLock)
            {
                Console.WriteLine("Balance before credit: {0}", balance);
                Console.WriteLine("Amount to add {0}", amount);
                balance = balance + amount;
                Console.WriteLine("Balance before credit: {0}", balance);
            }
        }
    }
    class AccountTest
    {
        static void Main()
        {
            var account = new Account(10000);
            var tasks = new Task[1000];
            for (int i = 0; i < tasks.Length; i++)
            {
                tasks[i] = Task.Run(() => RandomlyUpdate(account));
            }
            try
            {
                Task.WaitAll(tasks);
            }
            catch (Exception ex)
            {
                Console.WriteLine(" Exception msg {0}", ex.Message);
            }
            Console.ReadKey();
        }
        static void RandomlyUpdate(Account account)
        {
            var rnd = new Random();
            for (int i = 0; i < 10; i++)
            {
                var amount = rnd.Next(1, 100);
                bool doCredit = rnd.NextDouble() < 0.5;
                if (doCredit)
                {
                    account.Credit(amount);
                }
                else
                {
                    account.Debit(amount);
                }
            }
        }
    }
}
 Another example of lock:
 

In the following example, we shall show the output of the following listing with lock and without a lock. Without a lock, we see all threads are reading and writing at the same time. It can be harmful, for example, if we are reading a file and at the same time, another thread is trying writing. In this type of case, we must use a lock to protect data.

    class Program
    {
        static private object myLock = new object();
        static void Main(string[] args)
        {
            for (int i = 0; i < 5; i++)
            {
                new Thread(DoWork).Start();
            }
            Console.ReadKey();
        }
        static void DoWork()
        {            
             //Thread synchronisation lock
           // lock (myLock)
            {
                Console.WriteLine("Thread ID {0} Starting", Thread.CurrentThread.ManagedThreadId);
                Thread.Sleep(3000);
                Console.WriteLine("Thread ID {0} Completed", Thread.CurrentThread.ManagedThreadId);
            }
    }
}            
Lock statement is commented in the above code, the output of this code is as follows: As we can see all threads have started at the same times and doing some work (whatever it can be, accessing the file system, accessing shared variables with another thread)
Thread ID 7 Starting
Thread ID 3 Starting
Thread ID 6 Starting
Thread ID 4 Starting
Thread ID 5 Starting
Thread ID 3 Completed
Thread ID 5 Completed
Thread ID 4 Completed
Thread ID 6 Completed
Thread ID 7 Completed

Lock statement is not commented anymore, the output of this code is as follows: As we can see all threads can’t start at the same time (whatever it can do, accessing the file system, accessing shared variables with another thread). One thread is staring and it is finishing the task and after that next one is starting as seen in the output.

Thread ID 4 Starting
Thread ID 4 Completed
Thread ID 3 Starting
Thread ID 3 Completed
Thread ID 5 Starting
Thread ID 5 Completed
Thread ID 6 Starting
Thread ID 6 Completed
Thread ID 7 Starting
Thread ID 7 Completed
 

Thread Deadlock in C#

Deadlock example, deadlock is a situation where we are misusing the lock, specially when multiple lock objects are waiting for each other.  In the following code we can see how dead lock can happen. Lock is being called each other, results in deadlock. It is hard to debug. Run the following code and see that some statements are not executed at all, try to find the reason.

namespace deadlocktest
{
    class Program
    {
        static object object1 = new object();
        static object object2 = new object();
        public static void FunctionOne()
        {
            lock (object1)
            {
                Console.WriteLine("FunctionOne called 1");
                Thread.Sleep(1000);
                lock (object2)
                {
                    Console.WriteLine("FunctionOne called 2, never called");
                }
            }
        }
        public static void FunctionTwo()
        {
            lock (object2)
            {
                Console.WriteLine("FunctionTwo called 1");
                Thread.Sleep(1000);
                lock (object1)
                {
                    Console.WriteLine("FunctionTwo called 2, never called");
                }
            }
        }
        static void Main(string[] args)
        {
            Thread thread1 = new Thread(FunctionOne);
            Thread thread2 = new Thread(FunctionTwo);
            thread1.Start();
            thread2.Start();
            int i = 0;
            while (i < 9)
            {
                Console.WriteLine("How bad thread!");
                i++;
            }
            thread1.Join();
            thread2.Join();
            Console.ReadKey();
        }
    }
}

Download the threading example from this link.

AutoResetEvent 

Notifies a waiting thread that an event has occurred. Based on the event, system can allow the thread to run or block.

It is declared as follows:

private static AutoResetEvent anInitComplete = new AutoResetEvent(false);

We set the parameter to false if we want to block the thread, we set it to true if we allow the thread to continue. Here is a short console application that shows the idea. Please follow the explanation below.

 

namespace ConsoleApplication1
{
    class Program
    {
        public static bool Terminated
        {
            get
            {
                return terminated;
            }
        }
        private static AutoResetEvent anInitComplete = new AutoResetEvent(false);
        private static volatile bool terminated;
        static void Main(string[] args)
        {
            terminated = false;
            StartMessageLoopAndConnectToServers();
            anInitComplete.WaitOne();
            Console.WriteLine(">< Main");
            Console.ReadKey();
            terminated = true;
        }
        private static void StartMessageLoopAndConnectToServers()
        {
            Thread t = new Thread(ConnectToServersAndRunMessagePump);
            t.Start();
        }
        private static void ConnectToServersAndRunMessagePump(object obj)
        {
            while (!Terminated)
            {
                Console.WriteLine(">> ConnectToServersAndRunMessagePump");
                Thread.Sleep(5000);
                anInitComplete.Set();
                Console.WriteLine("<< ConnectToServersAndRunMessagePump");
            }
        }
    }
}

initialState: true to set the initial state to signaled; false to set the initial state to non-signaled.

If we pass true to AutoResetEvent in first place,  then anInitComplete.WaitOne() has no effect.  So output of method StartMessageLoopAndConnectToServers will be print later than when it prints  Main. If we pass false then WaitOne will block the thread and out of the thread function will be printed first.

Output of the program when passed false to AutoResetEvent
>> ConnectToServersAndRunMessagePump
<< ConnectToServersAndRunMessagePump
>> ConnectToServersAndRunMessagePump
>< Main
<< ConnectToServersAndRunMessagePump
>> ConnectToServersAndRunMessagePump
 
Output of the program when passed true to AutoResetEvent
>< Main
>> ConnectToServersAndRunMessagePump
<< ConnectToServersAndRunMessagePump
>> ConnectToServersAndRunMessagePump
<< ConnectToServersAndRunMessagePump
>> ConnectToServersAndRunMessagePump
 
Download the sample for testing with Visual Studio

 

Delegate and Lamda expression in C#

The delegate is a reference type data type that defines the method signature and similar to function pointer in C/C++.  It is declared in the following way:

[access modifier] delegate [return type] [delegate name]([parameters])

access modifier can be public, private etc

Here are few examples:

public delegate int MyDelegate(int x, int y);  //We can assign a function that takes 2 integer parameters and return type is integer
public delegate string MyDelegate(string firstname, int id); //We can assign a function that takes 2 parameters (first one string and second one integer) and return type is string.

 

public  delegate void MyDelegate(string message);
MyDelegate del = new MyDelegate(ArealMethod);
// or 
MyDelegate del = ArealMethod; 
// or set lambda expression  will be explained later
MyDelegate del = (string msg) =>  Console.WriteLine(msg);
// target method
static void ArealMethod(string message)
{
    Console.WriteLine(message);
}

Complete example:

    public class myApp
    {
        public delegate int MyDelegate(int x, int y);
        public static void Main()
        {
            MyDelegate del = new MyDelegate(Add);
            //Can be re written in the following way as well, compiler does the rest.
            int result = del(3, 4);
            Console.WriteLine(result); // the output will be 7, not a big deal

            del = Sub;
            result = del(3, 4);
            Console.WriteLine(result); // the output will be -1, not a big deal

            result = del.Invoke(10, 8); //Call the method by using Invoke
            Console.WriteLine(result);
            del = null;
            del += Add; //Method chain
            del += Sub;
            result = del.Invoke(14, 8); //Call the method by using Invoke, first it will call Add and then it will call Sub
            Console.WriteLine(result);

            Console.ReadKey();
        }
        public static int Add(int x, int y)
        {
            return x + y;
        }

        public static int Sub(int x, int y)
        {
            return x - y;
        }
    }

The output of the above program will be: If you see del has been set to null and then it has been chained with Add and Sub. When we do a chain then always the return value of the last method is returned.

7  
-1
2
6

 

Anonymous Method:

An anonymous method is a method without a name. Anonymous methods in C# can be defined using the delegate keyword.

Now in the above example, we can shorten the Add method by implementing it locally. This local implementation of the method without name, we call it anonymous method.

        public delegate int MyDelegate(int x, int y);
        public static void Main()
        {
            MyDelegate del = delegate (int x, int y)
            {
                return x + y;
            };
            int result = del(3, 4);
            Console.WriteLine(result); // the output will be 7, not a big deal
            Console.ReadKey();
        }
    }

 

As we see that content of Add method has been used locally  and the name Add has been removed, still we get the same result.

Lamda Statement:

It shorten further, remove delegate  keyword, put lamda expression symbol (=>) and remove return value, even variable type can be removed.

    public class myApp
    {
        public delegate int MyDelegate(int x, int y);
        public static void Main()
        {
            MyDelegate del =  (int x, int y) =>  x + y;
            int result = del(3, 4);
            Console.WriteLine(result); // the output will be 7, not a big deal
            Console.ReadKey();
        }
    }

If we remove the variable type, we can re write as follows:

MyDelegate del =  (x, y) =>  x + y;

If the original method Add had no parameter then we could have written as 

MyDelegate del =  () =>  10; //just return 10
    public class myApp
    {
        public delegate int MyDelegate();
        public static void Main()
        {
            MyDelegate del = () => 10;
            int result = del();
            Console.WriteLine(result); // the output will be 10
            Console.ReadKey();
        }
    }

Now MyDelegate returns void

    public class myApp
    {
        public delegate void MyDelegate();
        public static void Main()
        {
            MyDelegate del = () => Console.WriteLine("Now I am empty"); 
            del();
            //Console.WriteLine(result); // the output will be 7, not a big deal
            Console.ReadKey();
        }
    }

 

Same code written as multiline function this is called lamda statement.

 public class myApp
    {
        public delegate void MyDelegate();
        public static void Main()
        {
            MyDelegate del = () =>
            {
                Console.WriteLine("Now I am empty");
            };
            del();
            Console.ReadKey();
        }
    }

Expression lambda

If the right side of a lambda expression carries an expression tree then this kind of lambda expression is called an expression lambda. Yes, the example that we have see just now is one example of an expression lambda. Here is another one.

    //Lamda expression where we have only expression as shown in the following example
    public class myApp
    {
        public delegate bool MyDelegate( int x);
        public static void Main()
        {
            MyDelegate del = (x) =>
            {
                return x > 200;
            };
            Console.WriteLine(   del(29));
            Console.ReadKey();
        }
    }

 

Statement lambda

A statement lambda will contain a statement in the right hand side of the lambda expression. Have a look at the following example.

        MyDelegate del = () =>
        {
            int localvar = 200;
            Console.WriteLine("Now I am empty");
            Console.WriteLine("Now I am empty with {0}", localvar);
        };
        del();

Action, Func and Predicate are special type of lamda expression:

Action is a delegate (pointer) to a method, that takes zero, one or more input parameters, but does not return anything where as Func always return a value.

 

Func is a delegate (pointer) to a method, that takes zero, one or more input parameters, and returns a value (or reference). The last parameter is the return value.

 

Predicate is a special kind of Func often used for comparisons.

Though widely used with Linq, Action and Func are concepts logically independent of Linq.

Here is a small example for Action and Func without using Linq:

class Program
{
    static void Main(string[] args)
    {
        Action<int> myAction = new Action<int>(DoSomething);
        myAction(123); // Prints out "123"
        // can be also called as myAction.Invoke(123);
        Func<int, double> myFunc = new Func<int, double>(CalculateSomething);
        Console.WriteLine(myFunc(5));   // Prints out "2.5"
    }
    static void DoSomething(int i)
    {
        Console.WriteLine(i);
    }
    static double CalculateSomething(int i)
    {
        return (double)i/2;
    }
}

 

The Predicate delegate represents the method that defines a set of criteria and determines whether the specified object meets those criteria. In the following example, filtered will be a list of integer with positive numbers.

    //Predicate

    public class myApp
    {
        public static void Main()
        {
            var data = new List<int> { 1, -2, 3, 0, 2, -1 };
            var predicate = new Predicate<int>(isPositive);
            var filtered = data.FindAll(predicate);
            Console.WriteLine(string.Join(",", filtered));
            Console.ReadKey();
        }
        static bool isPositive(int val)
        {
            return val > 0;
        }
    }

Download the sample.

 

Events in C#

Events are user actions such as keypress, clicks, mouse movements, etc., or some occurrence such as system generated notifications. Applications need to respond to events when they occur. For example, interrupts. The events are declared and raised in a class and associated with the event handlers using delegates within the same class or some other class. The class containing the event is used to publish the event. This is called the publisher class. Some other class that accepts this event is called the subscriber class. 

In C#, the event is implemented with the help of a delegate. One of the most important properties of the delegate is that method chain. Several methods can be chained with delegates provided if those methods have the same signature.

 class Program
    {
        public delegate int MyDelegate(int x, int y);
        public static void Main()
        {
            MyDelegate readyforChained = new MyDelegate(Add);
            readyforChained += Sub;
            readyforChained += Multi;
            int x = readyforChained(10, 5); //only return the last method's return value
            Console.WriteLine("readyforChained returns {0}", x);
            Console.ReadKey();
        }
        public static int  Add(int x, int y)
        {
            Console.WriteLine("Add");
            int z = x + y;
            return z;
        }
        public static int Sub(int x, int y)
        {
            Console.WriteLine("Sub");
            int z = x - y;
            return z;
        }
        public static int Multi(int x, int y)
        {
            Console.WriteLine("Multi");
            int z = x * y;
            return z;
        }
    }

Output of the above program is, 3 methods have been chained Add, Sub  and Multi (All are taking similar parameters and returns the same type)

Add
Sub
Multi
readyforChained returns 50

Same example but the delegate now part of another class and we are using lambda than the original example, Also we are calling the chained delegate for several variables. It does the same but creates a base for the event. If we don’t add the method to the OnSomeAction delegate and in that case OnSomeAction will be null and the method will not be called.

public class ResultChecker
{
    public delegate int MyDelegate ( int x, int y );
    public MyDelegate OnSomeAction { get; set; }
    public int RaiseEvent ( int x, int y )
    {
        int result = 0;
        if (OnSomeAction != null)
        {     
            result = OnSomeAction (x, y );
        }
        return result;
    }
}
    class Program
    {
        public static void Main()
        {
            ResultChecker checker = new ResultChecker();
            checker.OnSomeAction +=  (x, y) => { Console.WriteLine("Add"); return x + y; };
            checker.OnSomeAction += (x, y) => { Console.WriteLine("Sub"); return x + y; };
            checker.OnSomeAction += (x, y) => { Console.WriteLine("Multi"); return x * y; };
            Console.WriteLine(checker.RaiseEvent(30, 20));
            //Call all assigned method  by delegate
            checker.OnSomeAction(20, 3);
            checker.RaiseEvent(3, 5);
            Console.ReadKey();
        }
    }
Add
Sub
Multi
600
Add
Sub
Multi
Add
Sub
Multi

The above text will be output of the program. Now we turn the example by introducing event. The event is just a glorified delegate.

 

        public class ResultChecker
        {
            public delegate int MyDelegate(int x, int y);
            public event MyDelegate OnSomeAction;
            public int RaiseEvent(int x, int y)
            {
                int result = 0;
                if(OnSomeAction != null)
                {
                    if(x >= 100 && y >= 100)
                    {
                        result = OnSomeAction(x, y);
                    }
                }
                return result;
            }
        }
        public class myApp
        {
            public static void Main()
            {
                ResultChecker checker = new ResultChecker();
                checker.OnSomeAction += (x, y) => { Console.WriteLine("Add"); return x + y; };
                checker.OnSomeAction += (x, y) => { Console.WriteLine("Sub"); return x + y; };
                checker.OnSomeAction += (x, y) => { Console.WriteLine("Multi"); return x * y; };
                checker.OnSomeAction += checker_OnSomeAction;
                Console.WriteLine(checker.RaiseEvent(60, 10)); // does not call method
                Console.WriteLine(checker.RaiseEvent(600, 100));
            }
            static int checker_OnSomeAction(int x, int y)
            {
                Console.WriteLine("Div"); return (int)(x / y);
            }
        }

Introducing EventArgs to indicate who is generating the event.    

        public class NumberArgs:EventArgs
        {
            public NumberArgs(int _x, int _y)
            {
                x= _x;
                y= _y;
            }
            public int x { get; set; }
            public int y { get; set; }
        }
        public class ResultChecker
        {
            public delegate void EventHandler(object sender, EventArgs e);
            public event EventHandler OnSomeAction = delegate { };
            public void CallMethod(int x, int y)
            {
                if(x >= 100 && y >= 100)
                {
                    OnSomeAction(this, new NumberArgs(x, y)); 
                }
            }
        }
        public class myApp
        {
            public static void Main()
            {
                ResultChecker checker = new ResultChecker();
                checker.OnSomeAction += checker_OnSomeAction;
                checker.CallMethod(600, 100);
            }
            static void checker_OnSomeAction(object sender, EventArgs e)
            {
                Type type = sender.GetType();
                Console.WriteLine("type = {0}", type.ToString());
                if(e == EventArgs.Empty)
                {
                    Console.WriteLine("Event argument is null");
                }
                else
                {
                    Console.WriteLine("Event argument is not null");
                }
            }
        }

 

Download example sample