Archive

Archive for March, 2011

Cancel BackgroundWorker threads when closing windows / applications

March 31, 2011 1 comment

The System.ComponentModel.BackgroundWorker class is useful when doing large amounts of work while still keeping the UI responsive.  They do however need to be cleaned up manually if they are not complete when windows / forms are closed. 

The example below shows one way to implement a clean up system to ensure all workers are cancelled and disposed of properly when closing objects. 

The code below is a normal Background Worker Method that will never complete.  While this is not normal – this demonstrates the point that the background thread keeps running even when the UI window is closed.  The window is closed – but the object is not disposed (garbage collected) since a reference between the window and the worker still exists. 

Download Source Code here: WPFBackGroundWorkerDemo.zip

private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            BackgroundWorker bw = new BackgroundWorker();
            bw.WorkerSupportsCancellation = true;
            bw.DoWork += new DoWorkEventHandler(bw_DoWork);
            bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
            bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
        }

 void bw_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker bw = sender as BackgroundWorker;
            bool isRunning = true;
            double counter = 0;
            while(isRunning)
            {
                bw.ReportProgress(0, "Work is being done.... " + counter);
                counter++;
                Thread.Sleep(5000);
            }
        }

If we run this and put a break point on the Thread.Sleep(5000) section and look at the threads window we can see our background thread running.

image

Now we close the SecondWindow and look at the threads again (put break point after the sw.ShowDialog(); in the Main Window class.  You see the arrow shows we are now back on the main thread but the worker thread is still running.  If you put a break point inside the while loop – it will stop at the break point every 5 seconds even though the second window is no longer in view.

This poses issues with performance, cleanup, etc.  These items should be cleaned up when closing the parent window (note there are always some exceptions to this for calculation operations, etc).

1.  Add a List as a class variable

private List<BackgroundWorker> _workers = new List<BackgroundWorker>();

2.  Each time a background worker is created – add it to the list

 private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            BackgroundWorker bw = new BackgroundWorker();
            // Add the worker to the list of workers
            _workers.Add(bw);
            bw.WorkerSupportsCancellation = true;
            bw.WorkerReportsProgress=true;
            bw.DoWork += new DoWorkEventHandler(bw_DoWork);
            bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
            bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
            bw.RunWorkerAsync();
        }

3.  In the worker completed event – remove it from the list

void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            // Once we are finished with the work - remove it from the list
            BackgroundWorker bw = sender as BackgroundWorker;
            if(bw!= null && _workers.Contains(bw))
            {
                _workers.Remove(bw);
            }
        }

4.  At this point – the worker still performs the same – the next step is where the cancellation comes into play.  I added a method to check the worker list and cancel any workers that are in the list.  This is called before the form / window is closed. 

private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            // If the list is not null and has workers
            if(_workers != null && _workers.Count > 0)
            {
                // Loop through the list
                foreach (BackgroundWorker bw in _workers)
                {
                    // If the worker is busy - cancel it
                    if(bw.IsBusy)
                    {
                        bw.CancelAsync();
                    }
                }
            }
        }

5.  You must also add logic to the worker dowork() method to return if cancel selected. 

 while(isRunning)
            {
                if (bw.CancellationPending)
                    return;
                bw.ReportProgress(0, "Work is being done.... " + counter);

 

Now for the test. 

image

If you close the SecondWindow killing the background worker – the text box on the MainWindow will not update.  If you close without killing – the text box will keep updating. 

 

Download Source Code here: WPFBackGroundWorkerDemo.zip

How to Save Time by Automating your Development Process

March 24, 2011 Leave a comment

In some of my other posts I have talked about ways to speed up the process of delivering software.  Below is a bullet point list of items I have been involved in over the past couple of years.  From start to finish these steps have  improved the quality of our development teams and our products. 

 

Source Control – Team Foundation Server  (TFS)

I hear a lot of people downing TFS. However I have had nothing but good experiences using it.  Setting it up proved a pain (at least 2008) but with 2010 it has become much easier.  It integrates well with Visual Studio 2010 which is my main IDE thus is the perfect choice. 

Continuous Integration (CI)

Continuous Integration is the process of automating the build process from your source repository.  There are a few good products on the market but my favorite is TeamCity by JetBrains.  It is written in Java and seems to be the most flexible across many different languages and platforms.  The best part is it is free for the Professional edition which for my personal development environment is great.  There are a number of different build configurations and agents that are available.  It is the “manager” of our whole build process. 

CI includes

  • Building Source Code
  • Running Unit Tests
  • Running Integration Tests
  • Building the MSI installers
  • Starting the data generation processes
  • Other miscellaneous tasks

Installations

There are many ways to package software for installation.  Some of the more common vendors such as InstallShield and Wise allow for automating the building of the installer packages (MSI’s) so this can be incorporated with the CI server above.  Plus with the MSI’s you can script the installations with simple windows batch files. 

Testing Environments (QA)

In one of my previous posts I wrote about automating VMware workstation.  I have been doing this for over two years now and it works flawlessly. 

http://tsells.wordpress.com/2009/09/20/how-to-save-time-automating-vmware-workstation/

As a developer – I still automate and install the build locally so I can be more effective when working with our Quality Assurance Team to assess any anomalies that may occur between a development and production (installed) environment. 

Test Data

Test data is critical for developers and testers to be able to confirm the product is working as expected.  There are many different ways of developing this.  I personally have done this with SQL Scripts, 3rd party utilities, and now I am using a tool I built custom that builds databases for all supported database platforms. 

Summary of Process

  1. Developer checks in code throughout the day
  2. Source Code is downloaded and rebuilt continuously
  3. Unit / Integration Tests Executed
  4. Daily Build Runs (full build to use for the steps below)
  5. MSI installs build
  6. MSI’s deployed to Server
  7. Data is generated
  8. QA Testing environments are reset
    Once the developer checks the code in – there are NO man hours involved to setup the environments to be ready for testing.  When this was a manual process, it took at least 6 – 8 hours for the process to be completed by no less than 4 people. 

WPF DatePicker not updating SelectedDate Property

March 22, 2011 1 comment

I ran into some issues with the WPF Date Picker where typing in a date into the text box was not updating the underlying property when clicking on another function.  In my specific instance it had to do with focus and interop issues.

To get around this I changed my object binding from the SelectedDate Property to the Text property of the control.  This now allows me to validate the date as the user types as well as updates the underlying object immediately so when focus is changed I don’t have to worry about whether or not the bindings were applied in time.

 

Before

<DatePicker
   Name="MyDatePicker"
   SelectedDate="{Binding Path=ActualDate, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
   />

 

After

 

 <DatePicker
   Name="MyDatePicker"
   Text="{Binding Path=ActualDate, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, TargetNullValue=''}"
   />

 

Using Parallel For and Foreach Loops in .Net 4

March 3, 2011 2 comments

With the release of the .Net 4.0 framework a great new feature was released – Parallel Processing.  I know what you are thinking – this has been around forever.  Well that is true – but now it’s built into the framework.  The two features I like the most are the Parallel.For and Parallel.ForEach loops.  This speeds up processing in a big way.

Usage

Below is an example syntactical use of each statement.

Parallel.For

Parallel.For(0, 100, d =>
    {
        // Do processing here
        // d is the equivalent to i in a standard for loop             
    });

Parallel.ForEach

   List<int> numbers = new List<int>();
   Parallel.ForEach(numbers, n =>
       {
        // Do Processing here
        // n is the current item 
    });

Test

I built a sample program that demonstrates the difference in processing time using parallel versus non parallel processing.

Source Code: ParallelProcessingDemo.zip

The following were results from a laptop running this program.

Laptop Specs

  • Intel Core I5 CPU @2.4GHz
  • 4 Gigs Ram
  • 7200 RPM Hard Drive
    Number of Iterations Parallel Time (ms) Non Parallel Time (ms) Percent Reduction in Time
    1000 7 16 56.25 %
    10000 22 50 56.00 %
    100000 189 405 53.33 %
    1000000 1496 4054 63.09 %

Overall these results show a +50 percent improvement in processing time.  This can be improved based on the type of actions being done.

Cautions

When using any type of parallel operations one must be careful to not run into conditions where different threads are operating on the same data / variables.  This can produce unexpected results that are difficult to debug.

For in memory issues – one solution is to “lock” variables in memory when accessing across multiple threads.  An example is shown in the attached source code.  An array was used just for the locking purposes as the lock can only be put on a reference variable.

 int[] counter = new int[1];
            int numIterations = Convert.ToInt32(e.Argument);
            Parallel.For(0, numIterations, d =>
                    {
                        if (_bw.CancellationPending)
                            return;
                        double value = DoProcess(d);
                        double newvalue = value * 23;
                        // Add lock to prevent cross threading updates (lose cycles this way)
                        lock (counter)
                        {
                            counter[0]++;
                        }
                    });

When going to the file system be sure to check for file locks as well to prevent errors.

Source Code: ParallelProcessingDemo.zip

Follow

Get every new post delivered to your Inbox.