Find the vowels in a string with C# .NET

Here comes a classic developer interview question: write a function that accepts a string and returns the number of vowels that it contains. The vowels in the English language are the following: a, e, i, o u. We want the vowel search to be case-insensitive, i.e. AEIOU must also be counted. This should be a fairly simple problem with multiple solutions. We’ll look at three of them in this post but there are certainly more:

  • using a counter
  • using a regex
  • LINQ

Let’s start with the class skeleton:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Text.RegularExpressions;

namespace Algorithms
{
    public class CountVowels
    {
        public int FindVowels(string input)
        {
            return 0;
        }        
    }
}

Here comes a short set of unit tests:

using Microsoft.VisualStudio.TestTools.UnitTesting;
using Algorithms;

namespace Algorithms.Tests
{
    [TestClass]
    public class CountVowelsTests
    {
        [TestMethod]
        public void CountVowelsTest()
        {
            var findVowels = new CountVowels();
            Assert.AreEqual(0, findVowels.FindVowels(null));
            Assert.AreEqual(3, findVowels.FindVowels("Hello World!!!"));
            Assert.AreEqual(5, findVowels.FindVowels("afdfgehhiddfgOdfgdU"));
            Assert.AreEqual(3, findVowels.FindVowels("UOE"));
            Assert.AreEqual(0, findVowels.FindVowels("rtyplkjhgfdszxcvb"));
        }
    }
}

Let’s start with the most basic counter-based solution that most developers came across in an intro course:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Text.RegularExpressions;

namespace Algorithms
{
    public class CountVowels
    {
        public int FindVowels(string input)
        {
            return FindVowelsWithHelpArray(input);            
        }

        private int FindVowelsWithHelpArray(String inputString)
        {
            int vowelCounter = 0;

            if (inputString != null)
            {
                var vowels = new List<char>() { 'a', 'e', 'i', 'o', 'u' };
                foreach (char c in inputString.ToLower())
                {
                    if (vowels.Contains(c))
                    {
                        vowelCounter++;
                    }
                }
            }            

            return vowelCounter;
        }        
    }
}

We initialise the counter variable vowelCounter to 0. Then if the input string is not null then we create a list of chars to contain all the vowels we want to count. Then we iterate through the lower-cased string char by char and if the current char is part of the vowel list then we increase the counter. Finally we return the counter from the function.

Run the unit tests, they all pass.

Next, let’s take a look at the Regex solution:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Text.RegularExpressions;

namespace Algorithms
{
    public class CountVowels
    {
        public int FindVowels(string input)
        {
           //return FindVowelsWithHelpArray(input);
           return FindVowelsWithRegex(input);
        }

        private int FindVowelsWithHelpArray(String inputString)
        {
            abridged...
        }

        private int FindVowelsWithRegex(String inputString)
        {
            if (inputString == null) return 0;
            return Regex.Matches(inputString, "[aeiou]", RegexOptions.IgnoreCase).Count;
        }        
    }
}

We use the Regex.Matches (https://docs.microsoft.com/en-us/dotnet/api/system.text.regularexpressions.regex.matches?view=netcore-3.1) function to count all the matches in the incoming string. The match is based on a simple array that reflects the vowels that we want to find. I took a shortcut and added the built-in RegexOptions enumeration to make sure that the search is case-insensitive instead of expressing it directly in the Regex string.

Run the unit tests, they will all still pass.

Finally let’s see a LINQ-based solution. LINQ is very versatile and there are certainly multiple ways to solve this problem using LINQ expressions. We’ll go for the most straightforward one using the Count() function:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Text.RegularExpressions;

namespace Algorithms
{
    public class CountVowels
    {
        public int FindVowels(string input)
        {
           //return FindVowelsWithHelpArray(input);
           //return FindVowelsWithRegex(input);
           return FindVowelsWithLinq(input);
        }

        private int FindVowelsWithHelpArray(String inputString)
        {
            abridged
        }

        private int FindVowelsWithRegex(String inputString)
        {
            abridged
        }

        private int FindVowelsWithLinq(String inputString)
        {
            if (inputString == null) return 0;
            var vowels = new List<char>() { 'a', 'e', 'i', 'o', 'u' };
            return inputString.ToLower().Count(c => vowels.Contains(c));
        }
    }
}

We again use the list of vowels just like in the first solution. Then we use the Count() LINQ function to count the vowels. We do that by providing a lambda function to go through each character in the string and see if the vowel list contains the given character.

The unit tests will pass just like before.

Advertisement

Capitalise each word in a sentence using C# .NET

Here comes a classic developer interview problem: write a function that takes a string as a parameter and returns the same string with each word in that string capitalised. Examples:

InputOutput
hello worldHello World
a beautiful morningA Beautiful Morning
the show must go onThe Show Must Go On
i can’t help falling in love with youI Can’t Help Falling In Love With You

There are of course multiple solutions to this problem. In this post we’ll go through two of them. Since this blog is mostly dedicated to C# and .NET we’ll use C# but the solutions can easily be translated into other OOP languages.

Note that a third solution based on regex was posted by http://gravatar.com/wkinkeldei in the comment section below.

We can start with a skeleton class and a small set of unit tests.

Capitalise.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Algorithms
{
    public class Capitalise
    {
        public string CapitaliseWordsInSentence(string input)
        {
            return null;
        }        
    }
}

…and a corresponding set of unit tests:

using Algorithms;
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Algorithms.Tests
{
    [TestClass]
    public class CapitaliseTests
    {
        [TestMethod]
        public void CapitaliseWordsInSentenceTests()
        {
            Capitalise c = new Capitalise();
            Assert.AreEqual("Hello World", c.CapitaliseWordsInSentence("hello world"));
            Assert.AreEqual("A Beautiful Morning", c.CapitaliseWordsInSentence("a beautiful morning"));
            Assert.AreEqual("The Show Must Go On", c.CapitaliseWordsInSentence("the show must go on"));
            Assert.AreEqual("I Can't Help Falling In Love With You", c.CapitaliseWordsInSentence("i can't help falling in love with you"));
        }        
    }
}

If you run the unit tests then they will of course fail:

Assert.AreEqual failed. Expected:<Hello World>. Actual:<(null)>.

The first possible solution we’ll be looking at is based on a simple iteration. We iterate through each character in the input string. As soon as the character before the current one is equal to an empty space we capitalise the current char. Add the following function to the Capitalise class:

namespace Algorithms
{
    public class Capitalise
    {
        public string CapitaliseWordsInSentence(string input)
        {
            return CapitaliseWordsWithIteration(input);
        }

        private string CapitaliseWordsWithIteration(string input)
        {
            StringBuilder stringBuilder = new StringBuilder(input[0].ToString().ToUpper());
            for (int i = 1; i < input.Length; i++)
            {
                if (input[i - 1] == ' ')
                {
                    stringBuilder.Append(input[i].ToString().ToUpper());
                } else
                {
                    stringBuilder.Append(input[i]);
                }
            }
            return stringBuilder.ToString();
        }     
    }
}

We use a StringBuilder to build the return string character by character. By default we capitalise the first character to begin with. Then we start the iteration from the second character of the input string until its end. If the character before the current one, i.e. at position i - 1 is a whitespace then we capitalise the current char. Otherwise we just add the char to the StringBuilder as-is. Finally we return the final string.

Let’s re-run the unit tests:

OK, good.

Let’s try another approach based on substrings. We split the input string using a whitespace delimiter. Then we iterate through each element in the delimited array. We take the first character of each word, capitalise it, and push the rest of the word to it. We collect the capitalised words in a list which we then use to rebuild the sentence using string.Join. Here’s the function:

private string CapitaliseWordsWithSubstrings(string input)
        {
            List<string> elements = new List<string>();
            foreach(string s in input.Split(' '))
            {               
                elements.Add(s[0].ToString().ToUpper() + s.Substring(1));   
            }

            return string.Join(" ", elements);
        }

If you call this function from CapitaliseWordsInSentence then the tests should pass just like before:

public string CapitaliseWordsInSentence(string input)
{
      return CapitaliseWordsWithSubstrings(input);
     //return CapitaliseWordsWithIteration(input);
}

We can improve the CapitaliseWordsInSentence by adding guards against nulls and empty strings:

public string CapitaliseWordsInSentence(string input)
{
    if (string.IsNullOrEmpty(input))
    {
        return "";
    }
    return CapitaliseWordsWithSubstrings(input);
    //return CapitaliseWordsWithIteration(input);
}

That’s it really.

Monitoring Task cancellation in C# in a loop

You cannot directly interrupt a Task in .NET while it’s running. You can do it indirectly through the CancellationTokenSource object. This object has a CancellationToken property which must be passed into the constructor of the Task:

CancellationTokenSource cancellationTokenSource	= new CancellationTokenSource();
CancellationToken cancellationToken = cancellationTokenSource.Token;

The cancellation token can be used as follows:

Task newTask = Task.Factory.StartNew(() =>
{
	for (int i = 0; i < 100000; i++)
	{
		if (cancellationToken.IsCancellationRequested)
		{
			Console.WriteLine("Task cancel detected");
			throw new OperationCanceledException(cancellationToken);
		}
		else
		{
			Console.WriteLine(i);
		}
	}
}, cancellationToken);

We simply count up to 100000 in the Task body. Note the IsCancellationRequested property of the token. We monitor within the loop whether the task has been cancelled.

You can cancel the task by calling the Cancel() method of the cancellation token like this:

cancellationTokenSource.Cancel();

Note that this method only signals the wish to cancel a task. .NET will not actively interrupt the task, you’ll have to monitor the status through the IsCancellationRequested property. It is your responsibility to stop the task. In this example we throw an OperationCanceledException which is a must in order to correctly acknowledge the cancellation. If you forget this step then the task status will not be set correctly. Once the task has been requested the stop it cannot be restarted.

If that’s all you want to do, i.e. throw an OperationCanceledException, then there’s a shorter version:

cancellationToken.ThrowIfCancellationRequested();

This will perform the cancellation check and throw the exception in one step. The loop can thus be simplified as follows:

Task newTask = Task.Factory.StartNew(() =>
{
	for (int i = 0; i < 100000; i++)
	{
		cancellationToken.ThrowIfCancellationRequested();
		Console.WriteLine(i);					
	}
}, cancellationToken);

View the list of posts on the Task Parallel Library here.

Design patterns and practices in .NET: the Strategy Pattern

Introduction

The strategy pattern is one of the simplest patterns to implement. Have you ever written code with ugly if-else statements where you check some condition and then call another method accordingly? Even worse: have you written if-else statements to check the type of an object and then called another method depending on that? That’s not really object-oriented, right? The strategy pattern will help you clean up the mess by turning the if statements into objects – aka strategies – where the objects implement the same interface. Therefore they can be injected into another object that has a dependency of that interface and which will have no knowledge of the actual concrete type.

Read more of this post

Design patterns and practices in .NET: the Factory Patterns – concrete, static, abstract

Introduction

Factories are extremely popular among design patterns. I have never seen any reliable statistics on the usage of patterns but factories must be among the top three most used patterns. However, that is not to say that they are used correctly. Many developers misunderstand factories to factor out chunks of code to other classes where the factored-out code is encapsulated into a static method as follows:

double cost = CostFactory.Calculate(input params);

Read more of this post

Design patterns and practices in .NET: the Decorator design pattern

Introduction

The Decorator pattern aims to extend the functionality of objects at runtime. It achieves this goal by wrapping the object in a decorator class leaving the original object intact. The result is an enhanced implementation of the object which does not break any client code that’s using the object.

It is an alternative solution to subclassing: you can always create subclasses to an object to extend and modify its functionality but that can result in class-explosion. Class-explosion means that you create a large number of concrete classes from a base class to allow for the combination of different possible behaviour types. The result is a bloated class structure and a hard-to-maintain application.

The pattern supports the Open/Closed principle of SOLID software design: you don’t change the implementation of an existing object. Instead, you modify the object using a wrapper decorator class. All this happens dynamically at runtime, i.e. this is not a design time implementation. This yields another benefit: flexible design. Our application will be flexible enough to take on new functionality to meet changing requirements.

When is this pattern most applicable?

  • Legacy systems: changing legacy code can be nasty. It’s easier to modify existing code with decorators
  • Add functionality to controls in Windows Forms / WPF
  • Sealed classes: the pattern lets you change these classes despite they’re sealed

The key to understanding this pattern is wrapping: the decorator class behaves just like the object you’re trying to change by behaving like a wrapper of that object. The decorator will therefore have a reference to that object in its class structure. The pattern is also called the Wrapper pattern for exactly this reason. You can even have a chain of decorators by wrapping the decorator of the decorator of the decorator etc.

Demo with a Base Class

Fire up Visual Studio 2010 or 2012 and create a new Console application with the name you want. We’ll simulate a travel agency that offers 3 specific types of vacations: Recreation, Beach, Activity. Insert a base abstract class called Vacation:

public abstract class Vacation
	{
		public abstract string Description { get; }
		public abstract int Price { get; }
	}

Insert the following concrete classes:

public class Beach : Vacation
	{
		public override string Description
		{
			get { return "Beach"; }
		}

		public override int Price
		{
			get
			{
				return 2;
			}
		}
	}
public class Activity : Vacation
	{
		public override string Description
		{
			get { return "Activity"; }
		}

		public override int Price
		{
			get { return 4; }
		}
	}
public class Recreation : Vacation
	{
		public override string Description
		{
			get { return "Recreation"; }
		}

		public override int Price
		{
			get { return 3; }
		}
	}

The Main method in Program.cs is very simple:

static void Main(string[] args)
		{
			Beach beach = new Beach();

			Console.WriteLine(beach.Description);
			Console.WriteLine("Price: {0}", beach.Price);
			Console.ReadKey();
		}

I believe all is clear so far. Run the programme to see the output.

As time goes by customers want to add extras to their vacations: private pool, all-inclusive, massage etc. All of these can be added to each vacation type. So you start creating concrete classes such as BeachWithPool, BeachWithPoolAndMassage, ActivityWithPoolAndMassageAndAllInclusive, right?

Well, no, not really. This would be result in the aforementioned class-explosion. The amount of concrete classes in the application would grow exponentially as we add more and more extras and vacation types. This clearly cannot be maintained. Instead we’ll use the decorator pattern to decorate the concrete types with the extras.

Go ahead and insert the following decorator class:

public class VacationDecorator : Vacation
	{
		private Vacation _vacation;

		public VacationDecorator(Vacation vacation)
		{
			_vacation = vacation;
		}

		public Vacation Vacation
		{
			get { return _vacation; }
		}

		public override string Description
		{
			get { return _vacation.Description; }
		}

		public override int Price
		{
			get { return _vacation.Price; }
		}
	}

Note that the decorator also derives from the Vacation abstract class. The decorator delegates the overridden implemented getters to its wrapped Vacation object. The wrapped Vacation object is the one that’s going to be decorated. This will be the base class for the concrete decorators. So let’s start with the PrivatePool decorator:

public class PrivatePool : VacationDecorator
	{
		public PrivatePool(Vacation vacation) : base(vacation){}

		public override string Description
		{
			get
			{
				return string.Concat(base.Vacation.Description, ", Private pool.");
			}
		}

		public override int Price
		{
			get
			{
				return base.Vacation.Price + 2;
			}
		}
	}

This concrete decorator derives from the VacationDecorator class. It overrides the Description and Price property getters by extending those of the wrapped Vacation object. Let’s try to add a private pool to our beach holiday in Program.cs:

static void Main(string[] args)
		{
			Vacation beach = new Beach();
			beach = new PrivatePool(beach);

			Console.WriteLine(beach.Description);
			Console.WriteLine("Price: {0}", beach.Price);
			Console.ReadKey();
		}

Note that we first create a new Beach object, but declare its type as Vacation. Then we take the PrivatePool decorator and use it as a wrapper for the Beach. The rest of the Main method has remained unchanged. Run the programme and you’ll see that the description and total price include the Beach and PrivatePool descriptions and prices. Note that when we wrap the Beach object in the PrivatePool decorator it becomes of type PrivatePool instead of the original Beach.

Let’s create two more decorators:

public class Massage : VacationDecorator
	{
		public Massage(Vacation vacation) : base(vacation){}

		public override string Description
		{
			get
			{
				return string.Concat(base.Vacation.Description, ", Massage.");
			}
		}

		public override int Price
		{
			get
			{
				return base.Vacation.Price + 1;
			}
		}
	}
public class AllInclusive : VacationDecorator
	{
		public AllInclusive(Vacation vacation) : base(vacation)
		{}

		public override string Description
		{
			get
			{
				return string.Concat(base.Vacation.Description, ", All inclusive.");
			}
		}

		public override int Price
		{
			get
			{
				return base.Vacation.Price + 3;
			}
		}
	}

These two decorators have the same structure as PrivatePool, but the description and price getters have been modified of course. We’re now ready to add the all-inclusive and massage extras to our Beach vacation:

static void Main(string[] args)
		{
			Vacation beach = new Beach();
			beach = new PrivatePool(beach);
			beach = new AllInclusive(beach);
			beach = new Massage(beach);

			Console.WriteLine(beach.Description);
			Console.WriteLine("Price: {0}", beach.Price);
			Console.ReadKey();
		}

We keep wrapping the decorators until the original Beach object has been wrapped in a PrivatePool, an AllInclusive and a Massage decorator. The final type is Massage. The call to the Description and Price property getters will simply keep going “upwards” in the decorator chain. Run the programme and you’ll see that the description and price getters include all 4 inputs.

Now if the travel agency wants to introduce a new type of extra, all they need to do is to build a new concrete class deriving from the VacationDecorator.

The original Beach class is completely unaware of the presence of decorators. In addition, we can mix and match vacations types with their decorators. Our class structure is easy to extend and maintain.

Demo with an interface

You can apply the decorator pattern to interface-type abstractions as well. As you now understand the components of the pattern let’s go through one quick example.

Insert a class called Product and an interface called IProductService. Leave the product class empty. Insert a method into the interface:

public interface IProductService
	{
		IEnumerable<Product> GetProducts();
	}

Add a class called ProductService that implements IProductService:

public class ProductService : IProductService
	{
		public IEnumerable<Product> GetProducts()
		{
			return new List<Product>();
		}
	}

Using poor man’s dependency injection we can use the components as follows:

IProductService productService = new ProductService();
IEnumerable<Product> products = productService.GetProducts();
Console.ReadKey();

Nothing awfully complicated there I hope. Let’s say that you want to add caching to the Product service so that you don’t need to ask the product repository for the list of products every time. One option is of course to add caching directly into the body of the implemented GetProducts method. However, that is not the most optimal decision: it goes against the Single Responsibility Principle and reduces meaningful testability. It’s not straightforward to unit test a method that caches the results in its body. When you run the unit test twice, then you may not be able to get a reliable result from the method as it simply returns the cached outcome. Injecting some kind of caching strategy is a good way to go, check out the related Adapter pattern for more.

However, here we’ll take another approach. We want to extend the functionality of the Product service with a decorator. So let’s follow the same path as we did in the base class demo. Insert a decorator base as follows:

public class ProductServiceDecorator : IProductService
	{
		private readonly IProductService _productService;

		public ProductServiceDecorator(IProductService productService)
		{
			_productService = productService;
		}

		public IProductService ProductService { get { return _productService; } }

		public virtual IEnumerable<Product> GetProducts()
		{
			return _productService.GetProducts();
		}
	}

We follow the same principle as with the VacationDecorator class: we wrap an IProductService and call upon its implementation of GetProducts(). Let’s add the following cache decorator – you’ll need to add a reference to System.Runtime.Caching in order to have access to the ObjectCache class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Caching;
using System.Text;
using System.Threading.Tasks;

namespace Decorator
{
	public class ProductServiceCacheDecorator : ProductServiceDecorator
	{

		public ProductServiceCacheDecorator(IProductService productService)
			: base(productService)
		{ }

		public override IEnumerable<Product> GetProducts()
		{
			ObjectCache cache = MemoryCache.Default;
			string key = "products";
			if (cache.Contains(key))
			{
				return (IEnumerable<Product>)cache[key];
			}
			else
			{
				IEnumerable<Product> products = base.ProductService.GetProducts();
				CacheItemPolicy policy = new CacheItemPolicy();
				policy.AbsoluteExpiration = new DateTimeOffset(DateTime.Now.AddMinutes(1));
				cache.Add(key, products, policy);
				return products;
			}
		}
	}
}

We check the cache for the presence of a key. If it’s there then retrieve its contents otherwise ask the IProductRepository of the decorator base to carry out the query to the repository and cache the results. You can use these components as follows:

IProductService productService = new ProductService();
productService = new ProductServiceCacheDecorator(productService);
IEnumerable<Product> products = productService.GetProducts();
Console.ReadKey();

Run the programme and you’ll see that ProductServiceCacheDecorator takes over, runs the caching strategy and retrieves the products from the wrapped IProductService object.

View the list of posts on Architecture and Patterns here.

Continuation tasks in .NET TPL: many tasks continued by a single task

Tasks in .NET TPL make it easy to assign tasks that should run upon the completion of a certain task.

We’ll need a basic object with a single property:

public class Series
{
	public int CurrentValue
	{
		get;
		set;
	}
}

In previous installments of the posts on TPL we saw how to create tasks that are scheduled to run after a single task has completed: check here and here. It is also possible to create many tasks and a single continuation task that runs after all the antecedents have completed. The ContinueWhenAll() method takes an array or Task objects, all of which have to complete before the continuation task can proceed.

We create 10 tasks each of which increases the its local series value by 1000 in total in a loop:

Series series = new Series();

Task<int>[] motherTasks = new Task<int>[10];

for (int i = 0; i < 10; i++)
{
	motherTasks[i] = Task.Factory.StartNew<int>((stateObject) =>
	{
		int seriesValue = (int)stateObject;
		for (int j = 0; j < 1000; j++)
		{
			seriesValue++;
		}
		return seriesValue;
	}, series.CurrentValue);
}

All 10 tasks are antecedent tasks in the chain. Let’s declare the continuation task:

Task continuation = Task.Factory.ContinueWhenAll<int>(motherTasks, antecedents =>
{
	foreach (Task<int> task in antecedents)
	{
		series.CurrentValue += task.Result;
	}
});

continuation.Wait();
Console.WriteLine(series.CurrentValue);

We extract the series value from each antecedent task and increase the overall series value by the individual task results, i.e. a 1000. The lambda expression looks awkward a bit: the array of antecedent tasks appears twice. Once as the first argument to the ContinueWhenAll method and then as an input to the lambda expression.

There’s one more thing to note about the syntax: ContinueWhenAll of T denotes the return type of the antecedent tasks. You can also specify the return type of the continuation. Here’s a list of possibilities:

The continuation and the antecedent tasks both return an int:

Task<int> continuation = Task.Factory.ContinueWhenAll<int>(motherTasks, antecedents =>
{
	foreach (Task<int> task in antecedents)
	{
		series.CurrentValue += task.Result;
	}
	return 1234;
});

Continuation is void and antecedent tasks return an int:

Task continuation = Task.Factory.ContinueWhenAll<int>(motherTasks, antecedents =>
{
	foreach (Task<int> task in antecedents)
	{
		series.CurrentValue += task.Result;
	}
});

All of them are void:

Task continuation = Task.Factory.ContinueWhenAll(motherTasks, antecedents =>
{
	foreach (Task<int> task in antecedents)
	{
		//do something
	}
});

Continuation returns an int and antecedent tasks are void:

Task<int> continuation = Task<int>.Factory.ContinueWhenAll(motherTasks, antecedents =>
{
	foreach (Task<int> task in antecedents)
	{
		//do something
	}
	return 1234;
});

Note that it’s enough to start the antecedent tasks, which we did with Task.Factory.StartNew. The continuation task will be scheduled automatically.

View the list of posts on the Task Parallel Library here.

Continuation tasks in .NET TPL: continuation with many tasks

Tasks in .NET TPL make it easy to assign tasks that should run upon the completion of a certain task.

We’ll need a basic object with a single property:

public class Series
{
	public int CurrentValue
	{
		get;
		set;
	}
}

Declare and start a task that increases the CurrentValue in a loop and return the Series. This task is called the antecedent task in a chain of tasks.

Task<Series> motherTask = Task.Factory.StartNew<Series>(() =>
{
	Series series = new Series();
	for (int i = 0; i < 5000; i++)
	{
		series.CurrentValue++;
	}
	return series;
});

So this simple task returns a Series object with a current value property.

You can create other tasks that will continue upon the completion of the antecedent task. You can actually specify a condition when the continuation task should start. The default value is that the continuation task will be scheduled to start when the preceding task has completed. See the next post on TPL for examples.

You can combine continuations in different ways. You can have a linear chain:

  1. First task completes
  2. Second task follows first task and completes
  3. Third task follows second task and completes
  4. etc. with task #4, #5…

…or

  1. First task completes
  2. Second and thirds tasks follow first task and they all run
  3. Fourth task starts after second task and completes
  4. etc. with task #6, #7…

So you can create a whole tree of continuations as you wish. You can build up each continuation task one by one. Let’s declare the first continuation task:

Task<int> firstContinuationTask
	= motherTask.ContinueWith<int>((Task<Series> antecedent) =>
	{
		Console.WriteLine("First continuation task reporting series value: {0}", antecedent.Result.CurrentValue);
		return antecedent.Result.CurrentValue * 2;
	});

The first continuation task reads the Series object built by the antecedent, the “mother” task. It prints out the CurrentValue of the Series. The continuation task also returns an integer: the series value multiplied by two.

We’ll let a second continuation task print out the integer returned by the first continuation task. I.e. from the point view of the second continuation task the first continuation task is the antecedent. We can say that “motherTask” is the “grandma” 🙂

Task secondContinuationTask
	= firstContinuationTask.ContinueWith((Task<int> antecedent) =>
	{
		Console.WriteLine("Second continuation task reporting series value: {0}", antecedent.Result);
	});

Note that it’s enough to start the first task, which we did with Task.Factory.StartNew. The continuation tasks will be scheduled automatically.

Alternatively you can declare the continuation tasks in a chained manner:

motherTask.ContinueWith<int>((Task<Series> antecedent) =>
{
	Console.WriteLine("First continuation task reporting series value: {0}", antecedent.Result.CurrentValue);
	return antecedent.Result.CurrentValue * 2;
}).ContinueWith((Task<int> antecedent) =>
{
	Console.WriteLine("Second continuation task reporting series value: {0}", antecedent.Result);
});

View the list of posts on the Task Parallel Library here.

Thread safe collections in .NET: ConcurrentBag

Concurrent collections in .NET work very much like their single-thread counterparts with the difference that they are thread safe. These collections can be used in scenarios where you need to share a collection between Tasks. They are typed and use a lightweight synchronisation mechanism to ensure that they are safe and fast to use in parallel programming.

Concurrent bags

Concurrent bags are similar to concurrent stacks and concurrent queues but there’s a key difference. Bags are unordered collections. This means that the order of the items is not the same as how they were inserted. So concurrent bags are ideal if you would like to share a List of T generic collection among several tasks.

Important methods:

  • Add(T element): adds an item of type T to the collection
  • TryPeek(out T): tries to retrieve the next element from the collection without removing it. The value is set to the out parameter if the method succeeds. Otherwise it returns false.
  • TryTake(out T): tries to get the first element. It removes the item from the collection and sets the out parameter to the retrieved element. Otherwise the method returns false

The ‘try’ bit in the method names imply that your code needs to prepare for the event where the element could not be retrieved. If multiple threads retrieve elements from the same list you cannot be sure what’s in there when a specific thread tries to read from it.

Example

The example is almost identical to what we saw for the collections discussed previously in the posts on TPL.

Declare and fill a concurrent bag:

ConcurrentBag<int> concurrentBag = new ConcurrentBag<int>();

for (int i = 0; i < 5000; i++)
{
	concurrentBag.Add(i);
}

Next we’ll try to take every item from the bag. The bag will be accessed by several tasks at the same time. The counter variable – which is also shared and synchronised- will be used to check if all items have been retrieved.

int counter = 0;

Task[] bagTasks = new Task[20];
for (int i = 0; i < bagTasks.Length; i++)
{
	bagTasks[i] = Task.Factory.StartNew(() =>
	{
		while (concurrentBag.Count > 0)
		{
			int bagElement;
			bool success = concurrentBag.TryTake(out bagElement);
			if (success)
			{
				Interlocked.Increment(ref counter);
			}
		}
	});
}

The while loop will ensure that we’ll try to take the items as long as there’s something left in the collection.

Wait for the tasks and print the number of items processed – the counter should have the same value as the number of items in the bag:

Task.WaitAll(bagTasks);
Console.WriteLine("Counter: {0}", counter);

View the list of posts on the Task Parallel Library here.

Share data between Tasks using locks in .NET C#

You need to be careful when sharing mutable data across several tasks. If you don’t restrict the access to a shared variable then the tasks will all modify it in an unpredictable way. It’s because you cannot be sure how the tasks will be started and managed by the operating system: it depends on a range of parameters, such as the CPU usage, available memory, etc. If each task is supposed to modify a variable then maybe the first task won’t finish its work before the second task reads the same variable.

Consider the following:

class BankAccount
{
	public int Balance { get; set; }
}

The following code builds a list of tasks that each increase the balance by 1:

BankAccount account = new BankAccount();
List<Task> tasks = new List<Task>();

for (int i = 0; i < 5; i++)
{
	tasks.Add(Task.Factory.StartNew(() =>
	{
		for (int j = 0; j < 1000; j++)
		{
			account.Balance = account.Balance + 1;
		}
	}));
}
Task.WaitAll(tasks.ToArray());
Console.WriteLine(string.Concat("Expected value 5000", ", actual value ",account.Balance));

We expect the final balance to be 5000. Run the code and you will most likely get something less, such as 3856 or 4652. At times you get exactly 5000 but it’s unpredictable.

In such cases you need to identify the volatile critical regions in your code. In this example it’s simple:

account.Balance = account.Balance + 1;

It is the account balance that is modified by each thread so we need to lock it for access so that only one thread can modify it at a certain time. You can take the word “lock” almost literally as we use the lock keyword to do that. We take an object which will act as the synchronisation primitive. The lock object must be visible to all tasks:

object lockObject = new object();

You use the lock keyword as follows:

for (int i = 0; i < 5; i++)
{
	tasks.Add(Task.Factory.StartNew(() =>
	{
		for (int j = 0; j < 1000; j++)
		{
			lock (lockObject)
			{
				account.Balance = account.Balance + 1;
			}
		}
	}));
}

The volatile region of the code is locked using the lock object. The lock is released as soon as the current task has finished working with it.

Run the modified code and you should get the correct result.

View the list of posts on the Task Parallel Library here.

Elliot Balynn's Blog

A directory of wonderful thoughts

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog

WEB APPLICATION DEVELOPMENT TUTORIALS WITH OPEN-SOURCE PROJECTS

Once Upon a Camayoc

Bite-size insight on Cyber Security for the not too technical.

%d bloggers like this: