Welcome to the Asynchronous Programming series. In the previous three articles we explained the async and await keywords and the return type of asynchronous methods and tasks. You can read them here.
- Asynchronous programming in C# 5.0: Part-1: Understand async and await
- Asynchronous Programming in C# 5.0 Part 2: Return Type of Asynchronous Method
- Asynchronous Programming in C# 5.0 Part 3: Understand Task in Asynchronous programming.
In this article we will explain Exception Handling in asynchronous programming. I hope you are experienced with Exception Handling in C# but may not know how to implement Exception Handling in asynchronous programming. Let's see how to implement try-catch blocks in asynchronous programming. Have a look at the following code.
Traditional Try-Catch in Asynchronous programming
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading;
- using System.Threading.Tasks;
- namespace Asynchronious
- {
- class Test
- {
- public Task ShowAsync()
- {
- return Task.Run(()=>{
- Task.Delay(2000);
- throw new Exception("My Own Exception");
- });
- }
- public async void Call()
- {
- await ShowAsync();
- }
- }
- class Program
- {
- public static void Main(String [] args)
- {
- Test t = new Test();
- try
- {
- t.Call();
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex.Message);
- }
- Console.ReadLine();
- }
- }
- }
We have declared a Test class with an asynchronous function, ShowAsync(), that will throw an exception. One more function (Call) will call the ShowAsync() function. From the Main() function we are calling the Call() function wrapping try catch blocks. And we hope that in the catch block the exception will be handled. Have a look at the following output.
Oh! Catch is not handling an exception? Why? The reason is it's asynchronous in nature. As we know, in asynchronous programming, control does not wait for the function's result and it executes the next line. So when the function throws an exception, at that moment the program control is out of the try-catch block. This is the reason for it.
Implement try-catch within function
Let's implement a try-catch block within an asynchronous function. This is the solution to catch exceptions in asynchronous methods. Have a look at the following code. If you look closely inside the ShowAsync() function then you will find we have implemented a try-catch within Task.run(). Within Task.run() all processes are executed synchronously (in our example) . So, if there is any exception then it will be caught by the Exception Handling block.
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading;
- using System.Threading.Tasks;
- namespace Asynchronious
- {
- class Test
- {
- public Task ShowAsync()
- {
- return Task.Run(() =>
- {
- try
- {
- Task.Delay(2000);
- throw new Exception("My Own Exception");
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex.Message);
- return null;
- }
- });
- }
- public async void Call()
- {
- try
- {
- await ShowAsync();
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex.Message);
- }
- }
- }
- class Program
- {
- public static void Main(String [] args)
- {
- Test t = new Test();
- t.Call();
- Console.ReadLine();
- }
- }
- }
Now, you may ask a question. We have implemented a try catch block within Task and it's fine. But what need is there for implementing a try-catch within the Call() function? The reason is that when an asynchronous function fails to execute a Task, it throws a Task Cancelled exception. And we need to implement a mechanism to catch this exception.
Here is the output screen.
We are seeing that now the Exception Handling block is capable of the catching the exception.
Now the question is, is it possible to wrap a try-catch block over an asynchronous function as is done for traditional synchronous functions? The answer is, we can but with a limitation. What is the limitation? The exception should occur outside of Task process statement. Then Exception Handling block can catch the exception. Let's see the following example.
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading;
- using System.Threading.Tasks;
- namespace Asynchronious
- {
- class Test
- {
- public Task ShowAsync()
- {
- throw new Exception("My Own Exception");
- return Task.Run(() =>
- {
- Task.Delay(2000);
- });
- }
- public async void Call()
- {
- try
- {
- await ShowAsync();
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex.Message);
- }
- }
- }
- class Program
- {
- public static void Main(String [] args)
- {
- Test t = new Test();
- t.Call();
- Console.ReadLine();
- }
- }
- }
Here the exception occurs outside of the Task, now the exception is caught by the try catch block from the calling location. Here is the sample output.
Conclusion
This article has explained Exception Handling in asynchronous programming. Hope you have understood it. In the next article I would like to discuss a few more real-world examples of asynchronous programming.