Posted by: Zeeshan Amjad | September 25, 2011

WPF Threading with Lambda Expression Revisited


We already saw one example of using Lambda expression in WPF threading here. But there is one major problem in that program. If we enter a very large number, say 10 million, then our UI is not responsive at all for a long time (depends on the hardware and state of the computer at that time). If we want to make UI responsive then we should return the Dispatcher to the process to update the user interface. If we want to keep doing the background calculation at the same time. i.e. calculate the total number of prime less than given number (pi function mathematically) then we call the BeginInvoke method of Dispatcher class periodically. In our case we are calling this after check number of primes in every 1000 numbers batch.

We can do this by calling BeginInvoke recursively until the current number is less than the specified number and keep updating the label as well as adding the prime number in the list box. We already saw one example of calling lambda function recursively in C++ here. Now we are going to do something similar in C#. The C# syntax is very similar to C++ one the only difference is that we don’t have to specify square bracket i.e. [] (lambda operator or lambda capture clause). Here is a syntax to call BeginInvoke recursively.

Code Snippet
Action<int> func = null;

Dispatcher.BeginInvoke(DispatcherPriority.Background,
    func = (Action<int>)((number)=>
        {
            while (number % batchsize != 0 && number < maximum)
            {
                if (IsPrime(number))
                {
                    listPrime.Items.Add(number);
                    total++;
                }

                number++;
            }

            if (number < maximum)
            {                                
                Dispatcher.BeginInvoke(DispatcherPriority.Background,
                    func, ++number);
            }

            tbResult.Text = total.ToString();

        }), ++current);

 

Rest of the code is very similar to the previous program. Here is complete XAML of the program.

Code Snippet
<Window x:Class="WpfThreadPrime.MainWindow"
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
       Title="Threading Prime" Height="600" Width="300">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition Height="6*"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <TextBlock Grid.Column="0" Grid.Row="0" Margin="5" VerticalAlignment="Center">
            Enter number
        </TextBlock>
        <TextBox Grid.Column="1" Grid.Row="0" Margin="5" VerticalAlignment="Center" Name="txtNo"/>
        <TextBlock Grid.Column="0" Grid.Row="1" Margin="5"
                  VerticalAlignment="Center">
            Total number of Primes
        </TextBlock>
        <TextBlock Grid.Column="1" Grid.Row="1" Margin="5" Name="tbResult"
                  VerticalAlignment="Center"/>
        <ListBox Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="2"
                Margin="5" Name="listPrime"/>
        <Button Grid.Column="0" Grid.Row="3" Name="btnCalculate"
               Width="75" Height="35" Click="btnCalculate_Click">
            Calculate
        </Button>
        <Button Grid.Column="1" Grid.Row="3" Name="btnExit"
               Width="75" Height="35" Click="btnExit_Click">
            Exit
        </Button>
    </Grid>
</Window>

 

Here is complete C# code of the program.

Code Snippet
using System;
using System.Windows;
using System.Windows.Threading;

namespace WpfThreadPrime
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private int total = 0;
        private int maximum = 0;
        private const int batchsize = 1000;

        public MainWindow()
        {
            InitializeComponent();
        }

        private void btnExit_Click(object sender, RoutedEventArgs e)
        {
            Close();
        }

        private void btnCalculate_Click(object sender, RoutedEventArgs e)
        {
            if (Int32.TryParse(txtNo.Text, out maximum))
            {
                int current = 1;
                listPrime.Items.Clear();
                total = 0;

                Action<int> func = null;

                Dispatcher.BeginInvoke(DispatcherPriority.Background,
                    func = (Action<int>)((number)=>
                        {
                            while (number % batchsize != 0 && number < maximum)
                            {
                                if (IsPrime(number))
                                {
                                    listPrime.Items.Add(number);
                                    total++;
                                }

                                number++;
                            }

                            if (number < maximum)
                            {                                
                                Dispatcher.BeginInvoke(DispatcherPriority.Background,
                                    func, ++number);
                            }

                            tbResult.Text = total.ToString();

                        }), ++current);
            }
        }

        private bool IsPrime(int number)
        {
            for (int i = 2; i < (number / 2) + 1; i++)
            {
                if (number % i == 0)
                    return false;
            }

            return true;
        }
    }
}

 

Here is the output of the program if we input 10 million in the text box and press Calculate button. Be careful this will take a long time depends on the computer hardware and state at that time. This program also display the prime numbers up to that range in the list box.

WPFThreadingPrimeOutput

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Categories

%d bloggers like this: