Showing posts with label BackgroundWorker. Show all posts
Showing posts with label BackgroundWorker. Show all posts

Friday, September 30, 2011

Working with Thread Pool in C# (Dotnet)


What is Thread Pool?

Thread pool is collection of Threads which can be used to perform different tasks in background. All threads available in Thread Pool can be used as Background ThreadBackground thread runs asynchronously in background and remains main thread active (UI will be responsive). When you create and start Thread it takes some significant time to create it in memory, instead Thread pool can be used. Thread pool manages overhead to create and recycle threads. Thread pool keeps watch on total number of worker threads are running asynchronously if it reached to its limit then threads are queued up and wait until any of the thread finishes its task from Thread pool. This way thread pool reuses the threads and avoids the cost of creating new threads each time. We can explicitly set Max and Min limit of Threads that Thread Pool creates by calling ThreadPool.SetMaxThread and ThreadPool.SetMinThread methods respectively.


How to work with Thread Pool?

There are number of ways to use thread pool in your application.

1.       ThreadPool.QueueUserWorkItem
2.       Task Parallel Library (PLINQ)
3.       Delegates (asynchronous delegates)
4.       BackgroundWorker


ThreadPool.QueueUserWorkItem

Thread pool class provides facility to queue items using QueueUserWorkItem method. This method accepts WaitCallBack delegate. Let’s have a look on below code.

public static void Main()
{
    Console.WriteLine("Calling from Main Thread...");
    Console.WriteLine("Is Thread Pool Thread : " +
        Thread.CurrentThread.IsThreadPoolThread.ToString());

    ThreadPool.QueueUserWorkItem(DoSomething);
}

private static void DoSomething(object x)
{
    Console.WriteLine("Calling from Thread Pool's Thread...");
    Console.WriteLine("Is Thread Pool Thread : " +
        Thread.CurrentThread.IsThreadPoolThread.ToString());
    Console.WriteLine("Hi, I am using Thread Pool");
}

Output
Calling from Main Thread...
Is Thread Pool Thread : False
Calling from Thread Pool's Thread...
Is Thread Pool Thread : True
Hi, I am using Thread Pool

In above code, I have used ThreadPool.QueueUserWorkItem method to request queue for my task from Thread pool. This methods queue thread requested and allocate thread from thread pool class if available. This method accepts WaitCallBack delegate and as per delegate signature it accepts one argument of object type so I have added one argument to DoSomething method. In above code I have not passed any argument to DoSomething method so it will take null as default. Another interesting thing is you can check whether the thread is from Thread pool or not using Thread.CurrentThread.IsThreadPoolThread. This property returns true if the thread is from Thread pool and returns false if not.


Task Parallel Library (PLINQ)

Task Parallel Library is introduced with Dotnet Framework 4.0. We can use Task class of TPL to enter into Thread Pool. Task class provides Factory to start new task from Thread pool. Let’s have a look on below code.

public static void Main()
{
    Console.WriteLine("Calling from Main Thread...");
    Console.WriteLine("Is Thread Pool Thread : " +
        Thread.CurrentThread.IsThreadPoolThread.ToString());

    Task.Factory.StartNew(DoSomething);
}

private static void DoSomething()
{
    Console.WriteLine("Calling from Thread Pool's Thread...");
    Console.WriteLine("Is Thread Pool Thread : " +
        Thread.CurrentThread.IsThreadPoolThread.ToString());
    Console.WriteLine("Hi, I am using Thread Pool");
}

Output
Calling from Main Thread...
Is Thread Pool Thread : False
Calling from Thread Pool's Thread...
Is Thread Pool Thread : True
Hi, I am using Thread Pool

In above code, Task class used to start new thread from Thread pool. Task.Factory.StartNew method used to start thread from thread pool. StartNew method accepts delegate action as parameter.


Asynchronous Delegate

Asynchronous delegate internally uses thread from Thread Pool class. You can pass arguments and return value from delegate method. Let’s have a look on below code.

public static void Main()
{
    Console.WriteLine("Calling from Main Thread...");
    Console.WriteLine("Is Thread Pool Thread : " +
        Thread.CurrentThread.IsThreadPoolThread.ToString());

    Func<string, int> MyDelegate = DoSomething;
    MyDelegate.BeginInvoke("Hello", null, null);
}

private static int DoSomething(string x)
{
    Console.WriteLine("Calling from Thread Pool's Thread...");
    Console.WriteLine("Is Thread Pool Thread : " +
        Thread.CurrentThread.IsThreadPoolThread.ToString());
    Console.WriteLine("Hi, I am using Thread Pool");
    return 0;
}

Output
Calling from Main Thread...
Is Thread Pool Thread : False
Calling from Thread Pool's Thread...
Is Thread Pool Thread : True
Hi, I am using Thread Pool

In above example, I made few changes in existing example and used asynchronous delegate. When you call BeginInvoke method of delegate it executes task in parallel thread and the thread will be pooled from ThreadPool class. I have created one Func<> delegate with string argument and integer as return type. This method is being executed in background thread of Thread pool class.


BackgroundWorker

Background worker class also uses thread from Thread pool to perform task in background. For more information about background worker you can go through my post on BackgroundWorker. Let’s have a look on below code
.
BackgroundWorker workerThread;

public static void Main()
{
    workerThread = new BackgroundWorker();
    workerThread.DoWork += new DoWorkEventHandler(workerThread_DoWork);
    workerThread.RunWorkerCompleted += new
        RunWorkerCompletedEventHandler(workerThread_RunWorkerCompleted);

    Console.WriteLine("Calling from Main Thread...");
    Console.WriteLine("Is Thread Pool Thread : " +
        Thread.CurrentThread.IsThreadPoolThread.ToString());
    workerThread.RunWorkerAsync();  
}
private void workerThread_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    Console.WriteLine("Worker thread completed.");
}

private void workerThread_DoWork(object sender, DoWorkEventArgs e)
{
    Console.WriteLine("Calling from Thread Pool's Thread...");
    Console.WriteLine("Is Thread Pool Thread : " +
        Thread.CurrentThread.IsThreadPoolThread.ToString());
    Console.WriteLine("Hi, I am using Thread Pool");
}

Output
Calling from Main Thread...
Is Thread Pool Thread : False
Calling from Thread Pool's Thread...
Is Thread Pool Thread : True
Hi, I am using Thread Pool
Worker thread completed.

As per above code, I have created one instance of BackgroundWorker class. I have also attached DoWork and RunWorkerCompleted methods to backgroundworker instance. So when I call RunWorkerAsync method of worker thread it will be executed on separate thread in background and thread will be pooled form Thread pool. When worker thread completes it will notify user with completed state.

As explained above, these all are the ways to use threads from Thread pool.

Hope you liked this post. Please leave your comments and feedback in comments section of this post.

See also –

Saturday, May 21, 2011

Windows 7 Task bar programming with WPF 4.0


Windows 7 Task Bar has so many new improved features and you can take full advantage of all features using WPF 4.0. You can customize Windows 7 task bar features like

  • Overlay Icons
  • Thumbnail Buttons
  • Progress Bar
  • Jump Lists

Overlay Icons

You can display application’s status using Overlay Icons. Overlay icons are small icons (size around 16 x 16 pixels) and can be set over your application’s icon. When you want to display your application’s status like your application is connected with service or playing audio or paying video etc. so you don’t need to replace your application’s icon instead you can set just overlay icon.

You just need to set any icon to overlay property of TaskbarItemInfo to display overlay icon in task bar along with application's icon. This also can be set from code behind based on different conditions.

<Window.TaskbarItemInfo>
  <TaskbarItemInfo 
          Overlay="/WPFApplication1;component/Images/video.ico" />
</Window.TaskbarItemInfo>





You can see video frame icon (small icon) on top of application icon is called as overlay icon. Based on overlay icon's status use can identify application’s status. As per above image user can easily understand that application is running some video. Likewise you can set different overlay icons based on different application’s state like running, stop, connected etc.  

Thumbnail Buttons

Thumbnail Buttons are small buttons can be placed over application icon. This can be displayed when you move mouse over the application’s task bar icon. Using these buttons you can interact with your application. These Thumbnail buttons interacts with your application from task bar and for that you need to add similar code which you may have already applied for existing button. Thumbnail buttons can be added in TaskbarItemInfo. 


The best example for thumbnail button is Media player in windows 7. You can play/pause media using thumbnail buttons from task bar. In below example I have created one Image Navigation Application and use Thumbnail button to navigate images.

<Window.TaskbarItemInfo>
<TaskbarItemInfo Overlay="/WPFApplication1;component/Images/video.ico"
                 x:Name="MyTaskItem"
                 ProgressState="Normal">
    <TaskbarItemInfo.ThumbButtonInfos>
        <ThumbButtonInfo x:Name="thumbPrevious"
              Description="Previous"
              ImageSource="/WPFApplication1;component/Images/rewind.ico"
              Click="thumbPrevious_Click" />
        <ThumbButtonInfo x:Name="thumbNext"
              Description="Next"
              ImageSource="/WPFApplication1;component/Images/forward.ico"
              Click="thumbNext_Click"/>
    </TaskbarItemInfo.ThumbButtonInfos>
</TaskbarItemInfo>
</Window.TaskbarItemInfo> 

private void thumbPrevious_Click(object sender, EventArgs e)
{
      setPreviousImage();
}
private void thumbNext_Click(object sender, EventArgs e)
{
      setNextImage();
}






















In first image you can see two Thumbnail buttons below the preview of  running application in task bar when you hover mouse over the application icon and in second image you can see the running application preview. 

This application used to navigate images. I can move to next and previous images using next/previous button and same time i can see preview of my current image. I have created two thumbnail buttons and applied functionality similar to Next/Previous button. Now i can navigate image from task bar only don't need to open application and click on next/previous button.

So using thumb button I can interact with application and do some important activities from task bar itself instead of doing it from application. You can use thumb button in your application for different purposes like start/stop service, Play/Pause Video etc.

Progress Bar

You can display progress of your application in task bar icon. For example when downloading is in progress you can see downloading progress from application’s icon in task bar. So you don't need to open application to check download progress. You can specify four types of progress state for you progress bar.

  • Normal - Progress bar icon is green and shows normal progress
  • Paused - Progress bar icon is yellow and shows paused progress
  • Indeterminate - Progress bar icon is green and shows indeterminate state.
  • Error – Progress bar icon is Red and shows error in progress.

<Window.TaskbarItemInfo>
    <TaskbarItemInfo x:Name="MyTaskItem"
                     ProgressState="Normal">
    </TaskbarItemInfo>
</Window.TaskbarItemInfo>


To specify current progress of your application use ProgressValue property of TaskBarItemInfo. ProgressValue property accepts value between 0 to 1. You can use BackgroundWorker to update ProgressValue property and let user notify when completed using RunWorkerCompleted event of BackgroundWorker. You can read more about BackgroundWorker here. It is not compulsory to use BackgroundWorker to set ProgressValue but recommended way to use. You can also use Timer instead. In below example for demo purpose i used timer to set ProgressValue.

void timer_Tick(object sender, EventArgs e)
{
      if (progresscount <= 100)
      {
    MyTaskItem.ProgressValue = (progresscount)/100;
           progresscount++;
      }
}






In above image you can see progress of your application in green color. So you can know how much progress is completed form task bar only. You don’t need to open application window to check progress.


JumpList

Jumplist is new feature of Windows 7 task bar and using WPF4 you can easily interact with this Windows7 Task bar feature. When you right click on application’s icon in task bar you can see few items under Task or Recent or most visited categories. Please have a look on below image





















Jump Lists can have two types of items Tasks and Paths. Tasks are nothing but shortcuts to other application and Paths are shortcuts to other file or folder. You can also enable built-in category called Recent and Frequent on you application’s Jumplist. To enable that you need to set ShowRecentCategory and ShowFrequentCategory properties to true in your application’s JumpList. You can add JumpList in your app.xaml file as well as in code behind.

<Application x:Class="WpfApplication1.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             StartupUri="Windows7TaskBar.xaml">
<Application.Resources>
</Application.Resources>
<JumpList.JumpList>
    <JumpList ShowRecentCategory="True"
              ShowFrequentCategory="True">
        <JumpPath Path="D:\Temp\" CustomCategory="MyCategory" />
        <JumpTask ApplicationPath="C:\Windows\Notepad.exe"
                  IconResourcePath="C:\Windows\Notepad.exe"
                  Description="Open Notepad"
                  Title="Notepad" />
        <JumpTask ApplicationPath="C:\Windows\System32\Calc.exe"
                  IconResourcePath="C:\Windows\System32\Calc.exe"
                  Description="Open Calculator"
                  Title="Calculator" />
    </JumpList>
</JumpList.JumpList>
</Application>

















You can see in above output, two tasks Notepad and Calculator added when you right click on your application’s icon in task bar. Similarly you can see recent and frequent files of your application please have a look on below snapshot of word application.



















WPF4 provides good and powerful features to interact with Windows7 Task bar Features. Using JumpList features you can provide good user interface for user to interact with you application as well other applications.


Hope you like this post and have better understanding about WPF4 task bar features. Please post your queries/feedback/comments here in comments section.  


Saturday, April 23, 2011

How to use BackgroundWorker to update UI in WPF


In this article I explained BackgroundWorker functionality using simple example. In this example I am adding millions of number in background to the Listbox. During this addition UI will be responsive and user can do some other work. When update complete it will notify user about the same.

BackgroundWorker in WPF

BackgroundWorker automatically perform task in separate thread and provide a notification to UI Thread when necessary. If you have long running task in your application you should consider putting this in separate background thread so that your UI remains responsive.

Whatever work you want to perform in background you can add it into DoWork event of BackgroundWorker. It has RunWorkerCompleted event too which fires when BackgroundWorker completes its task. So you can write some code in this event to notify user about completion of BackgroundWorker thread. To Start BackgroundWorker, use RunWorkerAsync method. When you call this method it will start executing code written in DoWork event.

XAML

<Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="0.1*"/>
            <RowDefinition />
            <RowDefinition Height="0.2*" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="100"/>
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <TextBlock Grid.Row="0" Grid.Column="0" Margin="5"
                   HorizontalAlignment="Right" Text="List of Numbers:" />
        <TextBlock Grid.Row="1" Grid.Column="0" Margin="5" Height="25"
                   HorizontalAlignment="Right" Text="" Name="Status"
                   Background="Yellow" VerticalAlignment="Top"/>
        <ListBox Grid.Row="0" Grid.Column="1" Name="NumbersList"
                 Grid.RowSpan="2"/>
        <Button Grid.Row="2" Grid.ColumnSpan="2" Height="30"
                Width="125" Content="Fill ListBox"
                Name="FillListBox" Click="FillListBox_Click" />
</Grid>

Code
        BackgroundWorker workerThread;
        public BackgroundWorkerSample()
        {
            InitializeComponent();
            workerThread = new BackgroundWorker();
            workerThread.DoWork += new DoWorkEventHandler(workerThread_DoWork);
            workerThread.RunWorkerCompleted += new
                RunWorkerCompletedEventHandler(workerThread_RunWorkerCompleted);
        }

        private void workerThread_RunWorkerCompleted(object sender,                                                              RunWorkerCompletedEventArgs e)
        {
            Status.Text = "Completed";
            FillListBox.IsEnabled = true;
        }

        private void workerThread_DoWork(object sender, DoWorkEventArgs e)
        {
            Action<int> workMethod = (i) => NumbersList.Items.Add("Number: " + i);
            for (int i = 0; i < 1000000; i++)
                NumbersList.Dispatcher.BeginInvoke(DispatcherPriority.Background, 
                workMethod, i);
        }

        private void FillListBox_Click(object sender, RoutedEventArgs e)
        {
            workerThread.RunWorkerAsync();
            FillListBox.IsEnabled = false;
            Status.Text = "Loading...";
        }