Async Await and Parallelism

In C#, async and await was first introduced in C# 5  detail explanation in MS Docs. You should go ahead and read those full articles. Starting from MVC 4, the async controller was introduced with async/await. Since then developers have been using async/await whenever possible.

What if a senior developer being asked: Hey explain async/await for juniors. We think we know something is just step 1. And that understanding might be wrong until we can explain to someone else.

Some believe that having asynchronous operations will make the system faster because more threads are used. Some say async will not block the main thread allowing better responsiveness of Windows Applications, or serving more requests in a Web Application.

How could we explain them? Not so many people have deep knowledge to dig deep in the low level implementation. Given that someone can (yes there are many of them), it is not easy to explain to others. Where is the balance? How about mapping the complex concept with something familiar?

I am not discussing the performance part, or will it be faster than sync. That is a complex topic and depending on many factors. Let’s analyze the serving more requests in a Web Application part.

Here is the truth, if you are in doubt ask Google

Async controller actions will allow a web application serves more requests.

Welcome to the Visa Department! You are here to get your Visa to US. There are 3 people in the department: Bob, John, and Lisa. Everyday there are hundreds of citizens come.

An applicant comes, Bob takes it. He does all the steps defined in the process. He might finish and come back 3 hours later. An applicant is solved and returned to the client.

When Bob is busy, John and Lisa take the next applicants and the process repeats. If Bob, John, and Lisa have not finished their applicants, there are just 3 applicants served. The rest has to wait.

There are 3 applicants served. The rest has to wait.

That is ASP.NET MVC synchronous controller in action. It blocks the processing pipeline.

The three decide to make a change. They organize their work and responsibilities

  1. Bob: Take incoming applicants. Put them on the boxes (labeled Requests Box) on tables next to him.
  2. John, Lisa: Take applicants in the boxes, proceed them. When an applicant is proceeded, put it in other boxes (labeled Responses Box) in the department.
  3. Whenever there is an applicant in the Responses Box, whoever (Bob, John, or Lisa) is free, take the applicant and return to the client.

What have changed in this model?

  1. Bob can take as many applicants as he can. Many clients are served.They can return to their seat, take a coffee and wait for the result.
  2. John and Lisa can coordinate or utilize the resources they have to finish the job.
  3. Anyone can return the result. Bob receives the applicant but maybe Lisa returns the result.

Is it faster to proceed one applicant? We do not know.

Can we serve many clients (applicants) in a day? Yes, definitely!

That is the ASP.NET MVC async controller in action.

Concept mapping

  1. Citizen (visa application): Request
  2. Visa Department: Web Server hosts the application.
  3. Bob, John, and Lisa: Thread
  4. Proceed an applicant: Application domain logic.
  5. Accept an applicant: Controller Action.

 

Ok Cool! Let’s see some code.

    public class ThreadModel
    {
        public int Id { get; set; }
        public string Message { get; set; }
    }
    public class ThreadTestController : Controller
    {
        [HttpGet]
        public async Task<ActionResult> Info()
        {
            var stopwatch = new Stopwatch();
            stopwatch.Start();
            var model = new List<ThreadModel>();
            model.Add(new ThreadModel
            {
                Id = Thread.CurrentThread.ManagedThreadId,
                Message = "Bob receives a visa applicant"
            });
            await Task.Delay(TimeSpan.FromSeconds(30));
            stopwatch.Stop();
            model.Add(new ThreadModel
            {
                Id = Thread.CurrentThread.ManagedThreadId,
                Message = $"Lisa returns the applicant after: {stopwatch.Elapsed}"
            });
            return Json(model);
        }
    }

And the outcome

[{"id":3,"message":"Bob receives a visa applicant"},
{"id":25,"message":"Lisa returns the applicant after: 00:00:30.0024240"}]

The request is handled at the thread 3 (Bob). And the response is handled at the thread 25 (Lisa). The elapsed time is 30 seconds.

Ok, then let’s see how long would it take if we await twice

    public class ThreadModel
    {
        public int Id { get; set; }
        public string Message { get; set; }
    }
    public class ThreadTestController : Controller
    {
        [HttpGet]
        public async Task<ActionResult> Info()
        {
            var stopwatch = new Stopwatch();
            stopwatch.Start();
            var model = new List<ThreadModel>();
            model.Add(new ThreadModel
            {
                Id = Thread.CurrentThread.ManagedThreadId,
                Message = "Bob receives a visa applicant"
            });
            await Task.Delay(TimeSpan.FromSeconds(30));
            await Task.Delay(TimeSpan.FromSeconds(30));
            stopwatch.Stop();
            model.Add(new ThreadModel
            {
                Id = Thread.CurrentThread.ManagedThreadId,
                Message = $"Lisa returns the applicant after: {stopwatch.Elapsed}"
            });
            return Json(model);
        }
    }

And the result

[{"id":29,"message":"Bob receives a visa applicant"},
{"id":32,"message":"Lisa returns the applicant after: 00:01:00.0099118"}]

It is 1 minute. Can we make it faster? How about this?

   public class ThreadTestController : Controller
    {
        [HttpGet]
        public async Task<ActionResult> Info()
        {
            var stopwatch = new Stopwatch();
            stopwatch.Start();
            var model = new List<ThreadModel>();
            model.Add(new ThreadModel
            {
                Id = Thread.CurrentThread.ManagedThreadId,
                Message = "Bob receives a visa applicant"
            });
            var t1 = Task.Delay(TimeSpan.FromSeconds(30));
            var t2 = Task.Delay(TimeSpan.FromSeconds(30));
            await Task.WhenAll(t1, t2);
            stopwatch.Stop();
            model.Add(new ThreadModel
            {
                Id = Thread.CurrentThread.ManagedThreadId,
                Message = $"Lisa returns the applicant after: {stopwatch.Elapsed}"
            });
            return Json(model);
        }
    }

Hey, look

[{"id":4,"message":"Bob receives a visa applicant"},
{"id":27,"message":"Lisa returns the applicant after: 00:00:30.0134799"}]

It is 30 seconds.

 

Asynchronous programming is a hard job. A proper understanding is very important. You do not understand unless you can explain.

Find the Devil in Log Files with PowerShell

Early morning, a good developer comes to the office, start his/her normal routine, checking his assigned tasks. Alert! Alert! there is a critical bug. The customer reported:

Error Code: ahde67g4-23ab-78bc-92ad-abhvbed753g2. Time: 2018-03-04 17:28:00

The system is well-design to not dispose any sensitive information. The system administrator send the development team a bunch of log files on that day.

So far so good except there are 4 servers, each server has around 20 files, each file has 20MB in size. In short, you have to find a golden piece of information among 80 files, 20MB each.

The system is designed in such a way that when a request comes in, it is assigned a unique GUID value. It is called CorrelationId. When a log entry is recorded, it has the CorrelationId. When a request fails, the CorrelationId is returned.

Having correlation id helps us trace everything happened in a request. When a request fails, we extract all the log entries having that correlation id.

Let’s see how we will handle it with the power of Powershell. Powershell is ship with Windows. You have it for free.

What do we have?

  1. A bunch of log files
  2. A keyword to search for: The CorrelationId or known as Error Code.

What do we need?

  1. All log entries of the CorrectionId.
  2. Extract them to a file so we can investigate deeper.

To many developers, it is a trivial task. But if this is the first time for you, it will be cool. I promise.

Servers Log

Inside a server

Log files from a server. Each file has a maximum of 20MB in size. There might be many files

Open PowerShell

In Explorer, navigate to the folder containing all the log files. There might be many subfolders grouped by server name.

Type “Powershell” in the address bar. PowerShell shows up with the current path.

Type Magic Command

dir -filter "*logging.txt.2018-03-04*" -recurse | select-string -pattern "ahde67g4-23ab-78bc-92ad-abhvbed753g2" | select-object -ExpandProperty Line > GoldenLog.txt

Explanation

There are 4 parts in that single-chained command.

dir -filter "*logging.txt.2018-03-04*" -recurse

It says: give me all the files having logging.txt.2018-03-04 in their name, including the files in subfolders. This command will allow us to narrow the searching on files occurred on 2018-03-04.

select-string -pattern "ahde67g4-23ab-78bc-92ad-abhvbed753g2"

Find all the lines (log entry) from files returned from the previous command having the keyword specified after the pattern. You can use a regular expression to expand the search.

If running the combination of the 2 commands, all the matching records are displaying right in the PowerShell editor. In many cases, that might be enough to find the information you need.

select-object -ExpandProperty Line

What you see on the PowerShell is a string representation of a matching object. The above command will extract the matching line, AKA a line in a log file.

> GoldenLog.txt

Finally stream the result to a text file. Having a text file allows you to explore deeper, at least in the case of many records returned.

 

Troubleshooting is a special job that requires a developer (or tester) uses various tools at hands. I would suggest you get started with PowerShell if you are on Windows. I started this blog post 2 weeks ago. I spent 2 weeks using what I wrote here to troubleshoot issues, to fix bugs. I am so happy that I utilize it. So should you when you give it a try.

C# Delegate

When was the last time you write code using delegate in C#? Hmm do you know what it means? To be honest, I have not used delegate keyword for years. Long time ago, when I wrote I had to google for the syntax. With the evolving of C#, we have not seen it being used in production code. But, it is important, or at least is nice, to know what it is.

Years ago, when I read about it, I did not understand at all. I could not wrap it up in my head. Therefore, I avoided to use it. Maybe because I did not understand the why behind the keyword.

Time flies. I am reading C# fundamentals again. Luckily, with 10 years of experience, I can understand the delegate keyword, not that bad.

Here is the official document from MS Doc. However, I would suggest you to read from Jon Skeet.

Such a definition might cause confusion and hard to understand. One way to understand a new concept is to map it with what we have known. I hope you can have your own mapping.

Let’s explore some examples to understand delegate. Imagine a context where there is a team which has a team leader and some developers. There are some bugs need to fixed in a week. The team leader has the responsibility of leading the team to finish the mission.

The example might confuse you because, well, it is an imaginary context. In the real life, or real project modeling, things are so much complicated. The main point is a playground to write some code with delegate, forget about all new fancy stuffs such as Action, Func, inline method, or expression.

Wire up a very simple .NET Core project using VS Code, here the first version I got (after some failing builds with first time using VS Code on Mac)

using System;
using System.Collections.Generic;
namespace funApp
{
    
    delegate void KillBug(Bug bug);
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello Team Leader");
            var tl = new TeamLeader();
            tl.StartSprint(new List<Bug>{
                new Bug("Fix homepage layout"),
                new Bug("Timeout exception when searching")
            });
            tl.RunSprint(new KillBug(SayBugName));
            
            Console.Read();
        }
        private static void SayBugName(Bug bug)
        {
            Console.WriteLine($"Hi {bug.Name}, how are you today?");
        }
        
    }
    class TeamLeader
    {
        private IList<Bug> _bugs = new List<Bug>();
        public void StartSprint(IList<Bug> bugsFromBacklog)
        {
            foreach (var bug in bugsFromBacklog)
            {
                _bugs.Add(bug);
            }
        }
        public void RunSprint(KillBug knowHowToKillBug)
        {
            foreach (var bug in _bugs)
            {
                knowHowToKillBug(bug);
            }
        }
    }
    class Bug
    {
        public string Name { get; set; }
        
        public Bug(string name)
        {
            Name = name;
        }
    }
}

It works.

The example demonstrates a very important concept in programming: Separation of Concern. Looking at the RunSprint method for a moment. A team leader usually does not know how to kill a bug, I know many team leaders are great developers, but they cannot kill all bugs themselves. They usually use ones who know how to kill a bug, which is usually a developer in his/her team. Or he can outsource to others, as far as they know how to kill a bug. That “know how to kill a bug” is modeled via a delegate “KillBug”.

In later version of C# (2, 3,..) and .NET, there are more options to rewrite the code to get rid of KillBug delegate declaration. But the concept remains.

       public void RunSprint(Action<Bug> knowHowToKillBug)
        {
            foreach (var bug in _bugs)
            {
                knowHowToKillBug(bug);
            }
        }

That method will produce the same outcome.

Do I need to know delegate to write C# code, to finish my job? No. You don’t.

Do I need to understand it? Yes. You should. Understanding the why behind the delegate concept is very important to make a proper design. Every feature has a good reason. We, developers, must understand that reason to make the best use.