Using the ValueTask of T object in C# 7.0

By now probably all .NET developers are aware of the await and async keywords, what they do and how they work.

Here’s a small example where the CalculateSum function simulates a potentially time-consuming mathematical operation:

public class AsyncValueTaskDemo
{
	public void RunDemo()
	{
		int res = CalculateSum(0, 0).Result;
		Console.WriteLine(res);
	}

	private async Task<int> CalculateSum(int a, int b)
	{
		if (a == 0 && b == 0)
		{
			return 0;
		}

		return await Task.Run(() => a + b);
	}
}

Read more of this post

Advertisement

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.

Share data between Tasks using locks in .NET C# in separate regions

In the this post we saw how to use the ‘lock’ keyword to restrict access to a single critical region. You can reuse the same lock object to synchronise access to the shared variable in separate regions. The modified version of the code in the referenced post looks as follows with two critical regions:

BankAccount account = new BankAccount();

List<Task> incrementTasks = new List<Task>();
List<Task> decrementTasks = new List<Task>();

object lockObject = new object();

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

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

Task.WaitAll(incrementTasks.ToArray());
Task.WaitAll(decrementTasks.ToArray());

Console.WriteLine(string.Concat( "Expected value: 0, actual value: ", account.Balance));

We have two sets of tasks: one that increases the balance and another that reduces it. By reusing the same lock object in both cases we can ensure that it’s always at most one task that has access to the shared variable.

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

Suspending a Task using Thread.Sleep in .NET C#

You may want to put a Task to sleep for some time. You might want to check the state of an object before continuing. The Task continues after the sleep time.

One way to solve this is using the classic Thread.Sleep method since the Task library uses .NET threading support in the background.

First construct your cancellation token:

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

Use this token in the constructor of the task:

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

Note the Sleep method where we suspend the Task for 10 seconds.

You can use the cancellation token to interrupt the task:

cancellationTokenSource.Cancel();

In the previous post we discussed how to suspend a task using the WaitOne method of the cancellation token. The main difference between WaitOne and Sleep is that Sleep will block even if the task is cancelled whereas WaitOne will exit if the cancellation come before the sleep time is over.

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

Exception handling in async methods in .NET4.5 MVC4 with C#

In this post we’ll take a look at how to handle exceptions that are thrown by actions that are awaited. My previous post already included some exception handling techniques in MVC4 but here we will concentrate on exceptions thrown by await actions. Check my previous 3 posts for the full story behind the code examples shown here.

We will simulate some problems by intentionally throwing an exception in GetResultAsync and GetDataAsync:

public async Task<String> GetDataAsync(CancellationToken ctk)
        {
            StringBuilder dataBuilder = new StringBuilder();
            dataBuilder.Append("Starting GetData on thread id ").Append(Thread.CurrentThread.ManagedThreadId)
                .Append(". ");
            ctk.ThrowIfCancellationRequested();
            await Task.Delay(2000);
            throw new Exception("Something terrible has happened!");
            dataBuilder.Append("Results from the database. ").Append(Environment.NewLine);
            dataBuilder.Append("Finishing GetData on thread id ").Append(Thread.CurrentThread.ManagedThreadId)
                .Append(".");
            return dataBuilder.ToString();
        }
public async Task<String> GetResultAsync(CancellationToken ctk)
        {
            StringBuilder resultBuilder = new StringBuilder();
            resultBuilder.Append("Starting GetResult on thread id ").Append(Thread.CurrentThread.ManagedThreadId)
                .Append(". ");
            ctk.ThrowIfCancellationRequested();
            await Task.Delay(2000);
            throw new Exception("The service is down!");
            resultBuilder.Append("This is the result of a long running calculation. ");
            resultBuilder.Append("Finishing GetResult on thread id ").Append(Thread.CurrentThread.ManagedThreadId)
                .Append(".");
            return resultBuilder.ToString();
        }

Also, increase the timeout value of the Index action so that we do not get a Timeout Exception:

[AsyncTimeout(4000)]
[HandleError(ExceptionType = typeof(TimeoutException), View = "Timeout")]
public async Task<ActionResult> Index(CancellationToken ctk)

Before you run the application change the ‘mode’ attribute of the customErrors element in the web.config to “Off” as we want to see the debug data.

It does not come as a surprise that we run into an exception:

Intentional exception YSOD

If you had worked with the TPL library before then you may have expected an AggregateException that wraps all exceptions encountered during the parallel calls. However, TPL behaves slightly differently in conjunction with the await keyword. It is still an AggregateException that is instantiated behind the scenes but the .NET runtime will only throw the first exception that was encountered during the method execution.

This is good news: we can set up our try-catch structures as usual; we don’t need to worry about inspecting an AggregateException anymore.

View the list of MVC and Web API related posts here.

Async controllers and actions in .NET4.5 MVC4 with C#

In the previous post we looked at the basics of async and await in a Console app. Now we’re ready to implement these new features in MVC4 to create async controllers.

The way to build asynchronous controllers has been completely changed compared to how it was done in MVC3 with the AsyncController superclass. This class and the inherent complexity in using it are gone in MVC4.

Start Visual Studio 2012 and create an MVC4 Web Application and choose the Internet template. Create a folder called “Services” in the solution. Insert two classes in this folder: DatabaseService and CalculationService. They represent long running calls to external services and have the following content:

DatabaseService.cs:

public class DatabaseService
    {
        public string GetData()
        {
            StringBuilder dataBuilder = new StringBuilder();
            dataBuilder.Append("Starting GetData on thread id ").Append(Thread.CurrentThread.ManagedThreadId)
                .Append(". ");
            Thread.Sleep(2000);
            dataBuilder.Append("Results from the database. ").Append(Environment.NewLine);
            dataBuilder.Append("Finishing GetData on thread id ").Append(Thread.CurrentThread.ManagedThreadId)
                .Append(".");
            return dataBuilder.ToString();
        }
    }

CalculationService.cs:

public class CalculationService
    {
        public string GetResult()
        {
            StringBuilder resultBuilder = new StringBuilder();
            resultBuilder.Append("Starting GetResult on thread id ").Append(Thread.CurrentThread.ManagedThreadId)
                .Append(". ");
            Thread.Sleep(2000);
            resultBuilder.Append("This is the result of a long running calculation. ");
            resultBuilder.Append("Finishing GetResult on thread id ").Append(Thread.CurrentThread.ManagedThreadId)
                .Append(".");
            return resultBuilder.ToString();
        }
    }

There should be nothing complicated in either class implementation.

Create another folder in the solution called ViewModels. Add a class called HomePageViewModel in that folder:

public class HomePageViewModel
    {
        public List<String> Messages { get; set; }

        public void AddMessage(string message)
        {
            if (Messages == null)
            {
                Messages = new List<string>();
            }
            Messages.Add(message);
        }
    }

Navigate to the Index action of the Home controller and modify it as follows:

public ActionResult Index()
        {
            DateTime startDate = DateTime.UtcNow;

            HomePageViewModel viewModel = new HomePageViewModel();
            viewModel.AddMessage(string.Concat("Starting Action on thread id ", Thread.CurrentThread.ManagedThreadId));
            CalculationService calcService = new CalculationService();
            DatabaseService dataService = new DatabaseService();

            viewModel.AddMessage(calcService.GetResult());
            viewModel.AddMessage(dataService.GetData());

            DateTime endDate = DateTime.UtcNow;
            TimeSpan diff = endDate - startDate;

            viewModel.AddMessage(string.Concat("Finishing Action on thread id ", Thread.CurrentThread.ManagedThreadId));
            viewModel.AddMessage(string.Concat("Action processing time: ", diff.TotalSeconds));
            return View(viewModel);
        }

Nothing complicated here either: we’re just adding messages to the view model, show the thread ids and measure the time it takes to complete the action.

Modify Index.cshtml of the Home view as follows:

@model Mvc4.ViewModels.HomePageViewModel
@{
    ViewBag.Title = "Home Page";
}

<ul>
    @foreach (String message in Model.Messages)
    {
        <li>@message</li>
    }
</ul>

So when you run the web page you should see an output similar to the following:

Screen with no async

It’s easy to see the following:

  • The Index() action blocks the thread when it calls CalculationService and DatabaseService
  • The total processing time took about 4 seconds in total
  • All involved methods executed on the same thread

Now our goal is to make this process more efficient: as it stands now the main thread is only sitting idle for most of the processing time. This can be a serious problem if we’re intending to build a scalable and responsive application.

We need to make a couple of changes to our code:

  • The Index() action needs to return a Task of type ActionResult and turned to an async method: we do not directly return an ActionResult but a Task that represents an ActionResult
  • Remember that if an action is of type async then it needs to have its pair ‘await’ somewhere in the method body
  • We have two long running method calls within the Index() action, so we’ll instruct MVC4 to await them
  • Since we’ll await those two method calls we need to insert async versions of DatabaseService.GetData() and CalculationService.GetResult() as well: they in turn must also return Tasks of type string instead of plain string

Using our experience from the Console app in the previous post we’ll include an async version of GetResult() in CalculationService.cs:

public async Task<String> GetResultAsync()
        {
            StringBuilder resultBuilder = new StringBuilder();
            resultBuilder.Append("Starting GetResult on thread id ").Append(Thread.CurrentThread.ManagedThreadId)
                .Append(". ");
            await Task.Delay(2000);
            resultBuilder.Append("This is the result of a long running calculation. ");
            resultBuilder.Append("Finishing GetResult on thread id ").Append(Thread.CurrentThread.ManagedThreadId)
                .Append(".");
            return resultBuilder.ToString();
        }

We’ll also insert a GetDataAsync() in DatabaseService.cs:

public async Task<String> GetDataAsync()
        {
            StringBuilder dataBuilder = new StringBuilder();
            dataBuilder.Append("Starting GetData on thread id ").Append(Thread.CurrentThread.ManagedThreadId)
                .Append(". ");
            await Task.Delay(2000);
            dataBuilder.Append("Results from the database. ").Append(Environment.NewLine);
            dataBuilder.Append("Finishing GetData on thread id ").Append(Thread.CurrentThread.ManagedThreadId)
                .Append(".");
            return dataBuilder.ToString();
        }

Update the Index action of the Home controller to call the async method versions of the services:

public async Task Index()
        {
            DateTime startDate = DateTime.UtcNow;

            HomePageViewModel viewModel = new HomePageViewModel();
            viewModel.AddMessage(string.Concat("Starting Action on thread id ", Thread.CurrentThread.ManagedThreadId));
            CalculationService calcService = new CalculationService();
            DatabaseService dataService = new DatabaseService();

            string calculationResult = await calcService.GetResultAsync();
            string databaseResult = await dataService.GetDataAsync();

            viewModel.AddMessage(calculationResult);
            viewModel.AddMessage(databaseResult);

            DateTime endDate = DateTime.UtcNow;
            TimeSpan diff = endDate - startDate;

            viewModel.AddMessage(string.Concat("Finishing Action on thread id ", Thread.CurrentThread.ManagedThreadId));
            viewModel.AddMessage(string.Concat("Action processing time: ", diff.TotalSeconds));
            return View(viewModel);
        }

Run the web app now and you may see an output similar to the following:

MVC screen with async in place

Note the following:

  • The Index action started on thread id 10
  • The same thread enters GetResultAsync
  • The main thread exits GetResultAsync at the await keyword and thread 9 takes over
  • Thread 9 enters GetDataAsync and exits at the await keyword and thread 5 takes over
  • Thread 5 finished Index()
  • The total processing time is still about 4 seconds, but remember from the previous post: if you want to couple asynchronous methods with concurrency you need to include the TPL as well. This will be resolved later in this post.

The output on your screen may be different when you run the sample. It is not guaranteed that 3 different threads will be involved throughout the lifetime of the Index() action. It depends on the availability of threads, may only be 2 in total.

If you are working with WCF services and add a service reference to your project then you’ll have the option to generate the Async() versions of the service calls automatically. Make sure to select the ‘Allow generation of asynchronous operations’ checkbox and the ‘Generate task-based operations’ radiobutton in the Service Reference Settings window.

.NET4.5 is now interspersed with built-in async versions of long running and/or remote methods. Typical examples include: HttpClient.SendAsync that returns a Task of type HttpResponseMessage, or HttpContent.ReadAsStringAsync that returns a Task of type String.

We can now introduce TPL to make the service calls run in parallel. As it stands now the Index action first waits for GetResultAsync to finish before it goes on with GetDataAsync. Ideally Index should wait for both actions to complete in parallel and not one after the other. We will basically hold a reference to the Task values returned by the services and await them both together.

Update the Index action as follows:

public async Task<ActionResult> Index()
        {
            DateTime startDate = DateTime.UtcNow;

            HomePageViewModel viewModel = new HomePageViewModel();
            viewModel.AddMessage(string.Concat("Starting Action on thread id ", Thread.CurrentThread.ManagedThreadId));
            CalculationService calcService = new CalculationService();
            DatabaseService dataService = new DatabaseService();

            Task<String> calculationResultTask = calcService.GetResultAsync();
            Task<String> databaseResultTask = dataService.GetDataAsync();

            await Task.WhenAll(calculationResultTask, databaseResultTask);

            viewModel.AddMessage(calculationResultTask.Result);
            viewModel.AddMessage(databaseResultTask.Result);

            DateTime endDate = DateTime.UtcNow;
            TimeSpan diff = endDate - startDate;

            viewModel.AddMessage(string.Concat("Finishing Action on thread id ", Thread.CurrentThread.ManagedThreadId));
            viewModel.AddMessage(string.Concat("Action processing time: ", diff.TotalSeconds));
            return View(viewModel);
        }

Note the following:

  • We do not await the two service calls one by one
  • Both of them will be awaited using Task.WhenAll
  • Task.WhenAll accepts an array of Task objects that should run in parallel
  • Task.WhenAll will block until all tasks in the array have finished
  • The await keyword will make sure that Index will wait upon all tasks to complete in the array
  • To retrieve the returned value from the service calls just use the Result property of the Task object: this will be populated if the Task has a return value i.e. it is a Task of some type

When you run the updated Index page you may see something like this:

Screen with async and TPL

Again, your results will almost certainly differ. Which thread is allocated to which task is up to the thread scheduler. Refresh the page a couple of times to see some different results.

In the next post we’ll wrap up the discussion with some miscellaneous issues such as timeouts or exception handling in conjunction with asynchronous controllers.

View the list of MVC and Web API related posts here.

Await and async in .NET 4.5 with C#

A goal for any dynamic application that is meant to handle lots of traffic is the optimal usage of server resources, including the processor. The application may need to perform processes that can be carried out on different threads. In this case it’s a waste of resources to let the actions be run one after the other on the same thread and have all other available threads lying idle. Typical examples include I/O operations and complex calculations that take long to complete that block the main thread which also handles the incoming requests and thereby reduce the scalability of the application.

There are two new keywords in .NET 4.5 that help increase the scalability of your application: async and await. Be aware that these techniques introduce threading on the server, i.e. they have nothing to do with AJAX. In this case our goal is to keep the server threads busy. Also, using these keywords alone will not automatically make your code run parallel: you’ll need to extend your solution with the Task Parallel Library (TPL).

Let’s first demonstrate the usage of TPL and async/await in a Console project. So fire up Visual Studio 2012 and create a Console app.

In the console app create a class called Operation. It is initially populated with two methods:


public class Operation
{
 public string RunSlowOperation()
 {
     Console.WriteLine("Slow operation running on thread id {0}", Thread.CurrentThread.ManagedThreadId);
     Thread.Sleep(2000);
     Console.WriteLine("Slow operation about to finish on thread id {0}", Thread.CurrentThread.ManagedThreadId);
     return "This is very slow...";
 }

 public void RunTrivialOperation()
 {
     string[] words = new string[] { "i", "love", "dot", "net", "four", "dot", "five" };
     foreach (string word in words)
     {
        Console.WriteLine(word);
     }
 }
}

We’ll print the starting and ending thread IDs of the slow operation.

Call both methods from Program.cs as follows:

public static void Main(string[] args)
        {
            Operation operation = new Operation();

            string result = operation.RunSlowOperation();
            operation.RunTrivialOperation();

            Console.WriteLine("Return value of slow operation: {0}", result);
            Console.WriteLine("The main thread has run complete on thread number {0}", Thread.CurrentThread.ManagedThreadId);
            Console.ReadLine();
            
        }

…we let both operations run one after the other and also print the ID of the main thread. The result may look similar to this:
Console output

It is not surprising that we first have to wait for the slow operation to finish before the trivial task can continue. The thread ID may differ when you run this example in your VS instance. However, note that the same thread handled Main and RunSlowOperation as well.

Now we’ll let TPL enter the picture. Extend the Operation class to include the following method:

public Task<string> RunSlowOperationTask()
        {
            return Task.Factory.StartNew<string>(RunSlowOperation);
        }

…so instead of directly returning the string result we’ll only return a Task representing a method that returns a string. Edit Program.cs to call this task and get its result by using the Task.Result property as follows:

public static void Main(string[] args)
        {
            Operation operation = new Operation();

            Task<string> result = operation.RunSlowOperationTask();
            operation.RunTrivialOperation();

            Console.WriteLine("Return value of slow operation: {0}", result.Result);
            Console.WriteLine("The main thread has run complete on thread number {0}", Thread.CurrentThread.ManagedThreadId);
            Console.ReadLine();
            
        }

When you run this then you will see that the slow operation did not block the main thread and the trivial operation could continue:
Console output

You’ll notice that the programme was carried out on two threads: one for the main thread and one for RunSlowOperation().

We’ll now include async and await to increase the efficient usage of our resources.

We can include the keyword async to method to make it asynchronous. An async method must have ‘await’ somewhere in its body otherwise the VS will complain. The await keyword indicates that the task it denotes can be suspended until some other task is complete. While the async method is suspended the caller is free to continue with what it is doing. This means that the thread that starts an async method may jump out of it at the await keyword and a different thread will jump in again and continue where the previous thread left off.

Async methods should always return a Task or a Task of T. The name of the async method should end with ‘Async’ to indicate to the caller that it is in fact an asynchronous method. The await keyword can occur more than once within the method body.

Extend Operation.cs to include the following method:

public async Task<string> RunSlowOperationTaskAsync()
        {
            Console.WriteLine("Slow operation running on thread id {0}", Thread.CurrentThread.ManagedThreadId);
            await Task.Delay(2000);
            Console.WriteLine("Slow operation about to finish on thread id {0}", Thread.CurrentThread.ManagedThreadId);
            return "This is very slow...";
        }

Note that Thread.Sleep was replaced by Task.Delay(2000). Thread.Sleep blocks the thread whereas Task.Delay represents a work that will block the thread for two seconds. At that point the thread that started the method may jump out of the method and let a different thread complete it to completion when the Task has finished.

Modify Program.cs as follows:

public static void Main(string[] args)
        {
            Operation operation = new Operation();

            Task<string> result = operation.RunSlowOperationTaskAsync();
            operation.RunTrivialOperation();

            Console.WriteLine("Return value of slow operation: {0}", result.Result);
            Console.WriteLine("The main thread has run complete on thread number {0}", Thread.CurrentThread.ManagedThreadId);
            Console.ReadLine();
            
        }

The output may look as follows:

Console output

We have some differences compared to the previous case:

  • The slow operation starts on the same thread as Main whereas it started on its own thread before
  • The slow operation completed on a different thread from the one that started it
  • The main thread jumped out of the long running method and continued with the trivial method of printing the string array elements

When the main thread encountered the await keyword it ‘knew’ that it could leave the long running method and let a different thread take over and finish it. The beauty of this is that the new thread that took over from the main thread will have the necessary context data available: HTTP context, identities, culture settings. The thread synchronisation job is taken care of by .NET behind the scenes.

Note that this behaviour is not guaranteed to occur: in some cases, such as Silverlight, the UI thread must stay constant. However, the benefit is that the UI will not freeze when it encounters a long running method: it can still stay active and react to user inputs.

To summarise:

  • Async and await help make the usage of processing threads more efficient
  • They will not make your code run parallel without the TPL
  • The thread that started an async method may not be the same as the one that finished the method
  • The available threads will not just lie idle and block incoming requests while waiting for a task to finish

In the next blog we’ll look at async/await in MVC4.

View the list of MVC and Web API related posts 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: