Showing posts with label C#. Show all posts
Showing posts with label C#. Show all posts

Sunday, 1 September 2013

C# Delegates Series Part 4 - Delegates can be used to Invoke methods asynchronously

Below is the reference of all posts in this series

  1. C# Delegates Series Part 1 - Overview
  2. C# Delegates Series Part 2 - Delegates allows methods to be passed as parameters
  3. C# Delegates Series Part 3 - Delegates can be used to define event handlers and event handling mechanism
  4. C# Delegates Series Part 4 - Delegates can be used to Invoke methods asynchronously

When Main UI thread invokes some method, main thread waits until that method completes and then continues with rest of the processing. This might turn out expensive in some scenarios where called method takes more time to execute or communicates with third party service or downloads a large file. This would make application less responsive. In such cases, delegates can be useful to call these methods asynchronously.

Note: BackgroundWorker class in C# is another powerful way to execute code asynchronously. BackgroundWorker also supports reporting progress, cancelling the thread and so on.

There are 4 different ways to invoke methods asynchronously using delegates with some variations.

1.   Call a Method Asynchronously using Delegate BeginInvoke and EndInvoke: In this approach, main thread will invoke other method using delegate BeginInvoke method. BeginInvoke initiates asynchronous call on separate thread and returns immediately so that main thread can continue with rest of the processing. Main thread can later call EndInvoke method to end the thread and return the result. If main thread has call EndInvoke and if method has not completed the execution, then main thread will wait for method to complete.

2.   Call a Method Asynchronously using WaitHandle: In this approach, the main thread will invoke other method using delegate BeginInvoke method, waits for a WaitHandle and then call EndInvoke().

3.   Call a Method Asynchronously in .NET using Polling: In this approach, Main thread will invoke other method using delegate BeginInvoke, continue with rest of the processing and periodically poll other thread/method (using IAsyncResult IsCompleted property) to check if method has completed the execution. During polling, if main thread finds that method has completed the execution (IsCompleted = true), delegate EndInvoke will be used to end the thread and return the result from method.

4.   Call a Method Asynchronously in .NET using Callback: In this approach, main thread will invoke other method using delegate BeginInvoke along with callback method passed as parameter and continue with rest processing. When other method completes the execution, it invokes callback method which is passed as delegate reference. This callback method will then call delegate EndInvoke to end the thread and return the result from method.

MSDN article provides a good description of these approaches along with examples.

C# Delegates Series Part 1 - Overview

At times, I have come across people who understand some basics of delegates but are really confused on when should they use delegates and how delegates are useful. During course of my development, I came across several scenarios where delegates were quite useful in achieving the desired functionality. So here is a series of delegates that would help you understand basic concepts of delegates and some scenarios  where delegates are useful.

  1. C# Delegates Series Part 1 - Overview
  2. C# Delegates Series Part 2 - Delegates allows methods to be passed as parameters
  3. C# Delegates Series Part 3 - Delegates can be used to define event handlers and event handling mechanism
  4. C# Delegates Series Part 4 - Delegates can be used to Invoke methods asynchronously

 

Let’s start with Overview of delegates

Delegates are similar to function pointers in C, C++. Delegates holds reference to function/method of same signature. When delegates are invoked, they in-turn invoke the function that is referenced. At first glance, it might seem difficult to understand why we need delegate and why can’t we call functions directly. Thinking of single class/file, it might not make much sense. But delegates starts getting useful when they span across multiple classes, multiple components, implementing event handles, callbacks, invoking functions asynchronously and so on. Don’t worry we would understands these scenarios in details as the article follows.

Let’s first understand steps involved in creating and using a simple delegate.

1.  Declaring delegate: A Delegate is a type that define method signature.

public delegate int MathDelegate(int a, int b);


2.  Creating method: Method that should be invoked when delegate is used.

public int Add(int a, int b)
{
return a + b;
}

public int Subtract(int num1, int num2)
{
return num1 - num2;
}

Here we define 2 methods that have same signature as delegate (return type, number of parameters and type of parameters).


Simply remove delegate keyword in step - 1 and replace MathDelegate with Add and this becomes our Add method signature.


It is not compulsory to match names of parameters. Check Subtract method where I have changed parameter name a with num1 and parameter name b with num2.


3.  Instantiate delegate: Create an instance of delegate and pass the function as parameter.

MathDelegate addDelegate = new MathDelegate(Add);
MathDelegate subtractDelegate = new MathDelegate(Subtract);

4.  Use delegate:

int result = addDelegate(10, 5);
MessageBox.Show(result.ToString());

result = subtractDelegate(10, 5);
MessageBox.Show(result.ToString());


Here, calling the delegate would invoke function that is referenced and return the result.



Now as we know what a delegate means, let’s understand some facts and real examples of delegate in next sequence of articles.

C# Delegates Series Part 3 - Delegates can be used to define event handlers and provide event handling mechanism

Below is the reference of all posts in this series

  1. C# Delegates Series Part 1 - Overview
  2. C# Delegates Series Part 2 - Delegates allows methods to be passed as parameters
  3. C# Delegates Series Part 3 - Delegates can be used to define event handlers and event handling mechanism
  4. C# Delegates Series Part 4 - Delegates can be used to Invoke methods asynchronously

Delegates are the base for Event handling mechanism in .net framework. Consider an example of Button Click event. Let’s see below code.

C# - Windows Forms

public Form1()
{
InitializeComponent();
btnSave.Click += btnSave_Click;
}

private void btnSave_Click(object sender, EventArgs e)
{

}

WPF

public MainWindow()
{
InitializeComponent();
btnSave.Click += btnSave_Click;
}

private void btnSave_Click(object sender, RoutedEventArgs e)
{

}

Here Click is the event of Button. btnSave_Click is the event handler/method that will be executed when button is clicked. Above syntax is called wiring event with event handler/method.


Now if we see the definition of button Click event  (Place cursor over Click keyword and Press F12 or right click on Click keyword and select go to definition), we find below code.


C# – Windows forms

public event EventHandler Click;

Drill down further to definition of EventHandler and we see below.

public delegate void EventHandler(object sender, EventArgs e);

So EventHandler is of type delegate that takes 2 arguments and returns nothing. Now if we see our definition of BtnSave method this would match with signature of delegate.


WPF

public event RoutedEventHandler Click;

Drill down further to definition of RoutedEventHandler and we see below.

public delegate void RoutedEventHandler(object sender, RoutedEventArgs e);

So RoutedEventHandler is of type delegate that takes 2 arguments and returns nothing. Now if we see our definition of BtnSave method this would match with signature of delegate.


That’s all about .net framework, now we see a real life example where we would find this useful.


There can be several examples.


Suppose you are designing a Login UserControl that takes login information from User. When user click OK button, you want en event to be fired on parent control (hosting Login UserControl) for further/additional processing.


In this post, we extend an example of our previous post where we created a Form that displays list of Assets. When user selects an Asset and clicks OK button, an event is fired in parent control (control that opened this Assets form) and selected asset information is passed to parent control.


Below is the code to achieve this functionality using delegates and events. In this post, we take an example of WPF application. Download the attached sample for complete example in C# console application, Windows forms and WPF.


Assets.xaml.cs


Assets page will load and displays list of assets in DataGrid. When user selects an asset in DataGrid and clicks OK button, an event should be fired in calling window that invoked Assets window. To achieve this we declare a delegate that can hold reference to method with one argument and returns no value. Then we create an event based on this delegate.

// Declare delegate
public delegate void AssetSelectedEventHandler(AssetItem item);

// Create event based on delegate
public event AssetSelectedEventHandler AssetSelected;

When user clicks OK button, we check if parent control (MainWindow in this case) has subscribed to this event by comparing AssetSelected to null and then we raise the AssetSelected event with argument as selected asset.

private void btnOK_Click(object sender, RoutedEventArgs e)
{
if (AssetSelected != null)
AssetSelected((AssetItem)AssetsGrid.SelectedItem);

this.Close();
}

MainWindow.xaml.cs


This is the main window that is displayed when application is started. In MainWindow, we load Assets.xaml window.

Assets assetSelector = new Assets(FilterMethod);
assetSelector.Owner = this;
assetSelector.AssetSelected += assetSelector_AssetSelected;
assetSelector.ShowDialog();
private void assetSelector_AssetSelected(AssetItem item)
{
// Here we get selected AssetItem information.
}

Code highlighted in yellow shows that “AssetSelected” event defined in Assets.xaml is attached to the event handler “assetSelector_AssetSelected”. Hence when AssetSelected event is raised in Assets.xaml window, assetSelector_AssetSelected event handler is called in MainWindown.xaml