Friday, February 11, 2022

Asynchrony in C#

 Here is a simple example of asynchronous programming in C#:

        async static Task Task1()
        {
            Console.WriteLine("Task 1");
        }

        async static Task Task2()
        {
            Console.WriteLine("Task 2");
        }

        async static void Main(string[] args)
        {
            await Task1();
            await Task2();
        }

A Main method sequentially calling two other methods - Task1 and Task2 respectively. Thanks to magic keywords - async and await this feels intuitive, almost like synchronous programming. Without those two the above code would probably look something like that:

        static void Task1()
        {
            Console.WriteLine("Task 1");
        }

        static void Task2()
        {
            Console.WriteLine("Task 2");
        }

         static void Main(string[] args)
        {
            var scheduler = TaskScheduler.FromCurrentSynchronizationContext();

            var task1 = Task.Factory.StartNew(() =>
            {
                Task1();
            }, default, TaskCreationOptions.None, scheduler);

            var task2 = task1.ContinueWith(task => {
                Task2();
            }, scheduler);

            task2
.Wait();
        }

Which is perfectly valid technically asynchronous programming, it's just not as elegant, although it certainly gives you deeper understanding of what's happening under the hood and most importantly much more control over the process. Speaking of control, have you ever heard of SynchronizationContext? You see, sometimes we find ourselves in a situation where there is only one thread allowed to execute specific code, for instance, a UI thread in WinForms or WPF application. What I mean is, in WinForms or WPF application all your event handlers gonna be executed on the same UI thread because their particular SynchronizationContext implementations were designed to be single-threaded. In case your wondering, WinForms implementation is WindowsFormsSynchronizationContext and WPF one is called DispatcherSynchronizationContext. So, if you have a bunch of calls and only one thread you need some kinda way to queue and order them and that's precisely what SynchronizationContext does. Or doesn't, depending on specific implementation. The default one is thread-free, which basically means it carelessly executes your tasks independently using ThreadPool.

Ok, now let's talk about ConfigureAwait. If your application has a SynchronizationContext, this means the compiler will try to execute continuations Task1 and Task2 on the same thread Main is being executed on:

        async static void Main(string[] args)
        {
            await Task1();
            await Task2();
        }

The above code is equivalent to this:

        async static void Main(string[] args)
        {
            await Task1().ConfigureAwait(true);
            await Task2().ConfigureAwait(true);
        }

But what about this one?

        async static void Main(string[] args)
        {
            await Task1().ConfigureAwait(false); /* Continuation of Main. */
            await Task2().ConfigureAwait(false); /* Continuation of Task1. */
            /* The rest of the body of Main, as in variable definitions, method calls and so on.
                Everything here is also gonna become a continuation.
            */

        }

In this case, you explicitly tell the compiler that you dont care in what SynchronizationContext and on what thread the continuations gonna be executed. This means:

  • Task1 can be executed on a different thread in a different SynchronizationContext than Main;
  • Task2 can be executed either on the same thread as Task1, which is faster than doing it on a different thread or it can be executed on any available thread;
  • Whatever comes after Task2 can be executed either on the same thread as Task2 or any available thread;

Underneath all that syntactic sugar there are three abstractions: TaskScheduler, SynchronizationContext and ThreadPool, specifically in that order.

  1. TaskScheduler schedules your tasks for execution.
  2. SynchronizationContext synchronizes task execution.
  3. ThreadPool executes your functions using a bunch of threads it's in charge of, so it couldn't care less about your asynchrony.

Here is how you create a TaskScheduler from the current SynchronizationContext:

        var scheduler = TaskScheduler.FromCurrentSynchronizationContext();

And that's how you create a continuation using a callback and the scheduler we
previously obtained from the current SynchronizationContext:

         static void Main(string[] args)
        {
            var scheduler = TaskScheduler.FromCurrentSynchronizationContext();

            var task1 = Task.Factory.StartNew(() =>
            {
                Task1();
            }, default, TaskCreationOptions.None, scheduler);

            var task2 = task1.ContinueWith(task => {
                Task2();
            }, scheduler);

            task2.Wait();
        }

That way, Main, Task1 and Task2 are gonna be executed on the same thread and in the same SynchronizationContext.

 

Sunday, November 12, 2017

Nullable in C#

Nullable is a special generic class meant to enable value types to be set to null.

Nullable<bool> nullableOfBool = false;
Nullable<int> nullableOfInt = 0;
Nullable<float> nullableOfFloat = 0.0f;

bool? nullableOfBool = false;
int? nullableOfInt = 0;
float? nullableOfFloat = 0.0f;

As you can see you can initialize them like if they were value types. Moreover, you can treat them like value types as long as you don't mix them with actual value types:

int? v1 = 1;
int? v2 = 7;
int? result = v1 + v2;

If for some reason you wanna access underlying type, you can do this by accessing Value property of Nullable:

int v1 = 1;
int? v2 = 7;
int result = v1 + v2.Value;

Or simply cast it to a corresponding value type:

int v1 = 1;
int? v2 = 7;
int result = v1 + (int)v2;

If you don't know if your nullable contains any value, use can check it using HasValue property.

Null-conditional operator in C#

Null-conditional operator is a new .NET feature meant to ease your life as a developer. Its primary purpose is NullReferenceException prevention. I'mma give you an example:

namespace ConsoleApp
{
    class Car
    {
        public string Brand { get; set; }
    }

    class Program
    {
        static void DoSomethingWithCar(Car car)
        {
            // This is where you omitted check for null.
            string brand = car.Brand; // And this is where you get into trouble.
        }
        static void Main(string[] args)
        {
            DoSomethingWithCar(null);
        }
    }
}

Now we can either add missing check or use null-conditional operator:

namespace ConsoleApp
{
    class Car
    {
        public string Brand { get; set; }
    }

    class Program
    {
        static void DoSomethingWithCar(Car car)
        {
            // Null-conditional operator checks if car is null and if it is,
            // prevents us from accessing Brand property and sets brand to null.
            string brand = car?.Brand;
        }
        static void Main(string[] args)
        {
            DoSomethingWithCar(null);
        }
    }
}

Let's slightly modify our example so you can see another use case of null-conditional operator:

namespace ConsoleApp
{
    class Car
    {
        public string Brand { get; set; }
    }

    class Program
    {
        static void DoSomethingWithCars(Car[] cars)
        {
            // Null-conditional operator checks if cars array is null and if it is,
            // prevents us from accessing its first element and returns null.
            Car car = cars?[0];
        }
        static void Main(string[] args)
        {
            DoSomethingWithCars(null);
        }
    }
}

As you can see null-conditional operator can be used with both dot operator and subscript operator (square brackets).

Default values in C#

Here is the thing, C# doesn't allow you to leave a variable unitialized. What I mean is that every time you create a variable it's automatically assigned some sorta default value.

Integral types:
sbyte 0
byte 0
short 0
ushort 0
int 0
uint 0
long 0l
ulong 0ul

Floating-point types:
float 0.0f
double 0.0d
decimal 0.0m

Boolean:
bool false

Any class, struct, including these two:
object null
string null

Enumerations:
enum 0 (value of the first enumerator)

Characters:
char '\0'

Thursday, October 26, 2017

Tiny SSH client in C#

There is very nice SSH library for .NET called SSH.NET. You can find it here:
https://github.com/sshnet/SSH.NET, also available as a nuget package, so you can install it in a couple of clicks. Here is a brief client example:

using Renci.SshNet;
using System;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Enter IP:");
            var ip = Console.ReadLine();

            Console.WriteLine("Enter username:");
            var username = Console.ReadLine();

            Console.WriteLine("Enter password:");
            var password = Console.ReadLine();

            using (var client = new SshClient(ip, username, password))
            {
                client.Connect();

                while (true)
                {
                    var input = Console.ReadLine();
                    if (input.Contains("exit my console app"))
                        break;

                    Console.WriteLine(client.RunCommand(input).Result);
                }
            }
        }
    }
}

OpenVPN Jumpstart

Yesterday I badly needed to establish VPN connection between two computers, nothing extraordinary, one server and one client. In order to accomplish this quite trivial task I created a key:

openvpn --genkey --secret whatever.key

and two configuration files for the server(192.168.1.1):

dev tun
ifconfig 10.0.0.1 10.0.02
secret whatever.key

and the client(192.168.1.2) respectively:

remote 192.168.1.1
dev tun
ifconfig 10.0.0.2 10.0.01
secret whatever.key

Then I just ran:

openvpn --config server.conf
openvpn --config client.conf

and surprisingly it worked :)

By the way, if you have some kinda firewall or something you might need to consider opening port 1194.

Expression Bodied Functions and Properties in C#

Since C# 6 you can take advantage of using much more laconic expression bodied functions. Oh, expression bodied basically means lambdish or just bodiless :)

using System;

namespace ConsoleApp
{
    class Program
    {
        static void ExpressionBodiedMethod(string str) => Console.WriteLine(str);

        static void Main(string[] args)
        {
            ExpressionBodiedMethod("Hello!");
        }
    }
}

That shortened syntax can also be used to create a getter-only property:

using System;

namespace ConsoleApp
{
    class Program
    {
        static string ExpressionBodiedReadOnlyPrpoperty => "Hello!";
        /*static string ExpressionBodiedReadOnlyPrpoperty { get; } = "Hello!";*/

        static void ExpressionBodiedMethod(string str) => Console.WriteLine(str);

        static void Main(string[] args)
        {
            ExpressionBodiedMethod(ExpressionBodiedReadOnlyPrpoperty);
        }
    }
}