November 2006 - Posts

Rob Windsor's Western User Group Tour 2006

That's right folks, I'm saddling up the team and hittin' the dusty trail with Cookie and Slim...

As a member of the MSDN Canada Speakers Bureau I'm lucky enough to get to travel across the country doing user group talks. The last two years I've gone east to New Brunswick so this year I decided to see if I could arrange a trip out west. Normally, organizing two or more talks in the same week is tricky but, with the help of the leaders of the groups I'm visiting, the tour plans came together very smoothly. Hopefully, the less than ideal weather the west has been experiencing of late will change so my travel from city to city will be as pleasant.

Here are the details of my trip. If you're in the area drop by and say Hi.

Regina .NET User Group
Monday, December 4 at 6:00pm
Introduction to Windows Communication Foundation (WCF)
http://www.reginadot.net/Home/tabid/36/ctl/Details/mid/384/ItemID/24/selecteddate/12/4/2006/Default.aspx

Victoria .NET Developers Association
Tuesday, December 5 at 6:30pm
Asynchronous Programming with .NET
http://vicdotnet.org/blogs/monthlymeetings/archive/2006/11/21/December-2006-Monthly-Meeting.aspx

The Calgary .NET User Group
Wednesday, December 6 at 5:00pm
A Lap Around the .NET Framework 3.0
http://www.calgaryug.net/

Edmonton .NET User Group
Thursday, December 7 at 5:30pm
Introduction to Windows Communication Foundation (WCF)
http://www.edmug.net/

Posted by windsor | with no comments
Filed under: ,

DevConnections 2006 - Day 0 and 1

This is my first DevConnections and I have to say I'm impressed. I was expecting something similar to the two VSLives I've attended in Toronto but there are ten times as many attendees here and the conference is more upscale. It's really more like a smaller version of TechEd.

The first two days were "Microsoft Days". There were keynotes both Monday night and Tuesday morning followed by breakout sessions the remainder of Tuesday. These were all given by people from Microsoft, mostly members of the product teams. 

The highlight of the two days was a slew of product news. There were announcements that Windows Vista, the .NET Framework 3.0, Office 2007, Windows SharePoint Services v 3.0 and likely some others that I missed have all RTM'd. These products should be available for download by MSDN subscribers and volume licensers soon and will be available for retail purchase early in the new year.

Posted by windsor | with no comments

Keep Client Applications Responsive with the BackgroundWorker

Many applications need to perform some kind of long-running task like downloading a file, performing a complex calculation, or retrieving data from a database. Executing these tasks can make your application become unresponsive and end up making your users anxious. Take too long performing the task and the user will be looking for the Task Manager to kill your application.

The solution to this problem is to execute the long-running task on a second (or background) thread. This allows the user interface thread to continue working keeping your application responsive, but it presents you with a new problem. Creating multi-threaded applications is difficult - well actually it’s easy - it’s doing so properly, following all the rules, and not coding yourself into an all night debugging session that’s truly hard.

To help address this issue Microsoft added the BackgroundWorker component to .NET 2.0. This component is easy to use and understand and makes programming multi-threaded applications (without explicitly creating and managing threads) much safer for the developer. The exploration of the BackgroundWorker will be done through the creation of a demo application.

For a more comprehensive discussion of the topics covered in this article and to see how to achieve the same results using previous versions of .NET, see Chris Sells three-part series entitled Safe, Simple Multithreading in Windows Forms (http://shrinkster.com/ddm).

Let's assume you have a simple application with a Button and a ProgressBar. The code below will simulate a long-running task by putting the user interface thread to sleep, one half second at a time, in a loop. The loop is used to allow the program to report progress back to the user via the ProgressBar.

Private Sub Button1_Click(...) Handles Button1.Click
  Button1.Enabled = False
  For i As Integer = 1 To 10
    ProgressBar1.Value = i * 10
    Threading.Thread.Sleep(500)
  Next
  MessageBox.Show("Done", "Demo")
  Button1.Enabled = True
End Sub

As it stands, clicking the Start Button will begin the long-running task and, while the ProgressBar will be updated as we iterate through the loop, the rest of the application will be unresponsive. You will not be able to move or resize the form until the loop completes. The remainder of this post will discuss how to convert this code to run the loop on a background thread via the BackgroundWorker component. It will also show how to upgrade the application to allow the long-running task to be cancelled.

First, declare a private field for the BackgroundWorker. Then in the Form’s Load event handler, create the instance of the BackgroundWorker and set its WorkerReportsProgress and WorkerSupportsCancellation properties to True. These properties are set to False by default as a performance optimization.

Private WithEvents _worker As BackgroundWorker
Private _working As Boolean
Private Sub Form1_Load(...) Handles MyBase.Load
  _worker = New BackgroundWorker
  _worker.WorkerReportsProgress = True
  _worker. WorkerSupportsCancellation = True
End Sub

Create an event hander for the BackgroundWorker’s DoWork event and copy the existing code from the Button’s Click event hander to the newly created method. The Button is going to be used to both start the long-running task as well as cancel it. In the Click event handler check if the BackgroundWorker is currently busy; if it is signal a request to cancel the task by calling CancelAsync otherwise begin the task by calling RunWorkerAsync. It is important to note that the call to CancelAsync does not immediately terminate the task, it just signals a request to cancel. The code running the task must check for the request and handle it appropriately (see below).


Private Sub Button1_Click(...) Handles Button1.Click
  If _worker.IsBusy Then
    _worker.CancelAsync()
  Else
    Button1.Text = "Cancel"
    _worker.RunWorkerAsync()
  End If
End Sub

The code copied to the DoWork event handler needs to be modified slightly. The code in this event handler executes on a background thread so it cannot safely update the user interface, thus the line that originally set the Value property of the ProgressBar has to be changed. Replace this line with a call to the ReportProgress method of the BackgroundWorker passing the percent completed as a parameter. This will trigger the ProgressChanged event where we can safely update the ProgressBar. In addition, this code has to check for a request from the user to cancel the task which can be done by inspecting the CancellationPending property of the BackgroundWorker.

Private Sub _worker_DoWork(...) Handles _worker.DoWork
  For i As Integer = 1 To 10
    _worker.ReportProgress(i * 10)
    Threading.Thread.Sleep(500)
    If _worker.CancellationPending Then
      e.Cancel = True
      Exit For
    End If
  Next
End Sub

Private Sub _worker_ProgressChanged(...) Handles _worker.ProgressChanged
  ProgressBar1.Value = e.ProgressPercentage
End Sub

Finally, the BackgroundWorker raises the RunWorkerCompleted event to notify the user interface that long-running task is done, either because it completed normally or because it was cancelled.

Private Sub _worker_RunWorkerCompleted(...) Handles _worker.RunWorkerCompleted
  Dim msg As String = "Done"
  If e.Cancelled Then
    msg = "Cancelled"
  End If
  Button1.Text = "Start"
  MessageBox.Show(msg, "Demo")
End Sub

This short example demonstrates the basic use of the BackgroundWorker. That is executing a long-running task on a background thread, showing progress, and allowing the user to cancel.

Posted by windsor | with no comments

DevConnections 2006 - Viva Las Vegas

I've been teaching a lot lately, virtually every week for the last five or six months and I'm pretty burnt out. <aside>I know - WAAAAA poor baby has to work almost every week, life is really tough. Trust me, teaching a four day course is far more draining than you'd imagine. Doing it several weeks in a row, combined with travel, is killer.</aside> I had a few weeks open in November (note the had - they are all filled now) so I thought a week away would do wonders to rejuvenate me. As I was searching the internet for possible places to go I got an email from my MVP lead about some details around the DevConnections conference in Las Vegas in November. I love Vegas, I love Code, I love Geeks (usually in a very platonic way), so my decision was made - a perfect combination of vacation, technical material, and catching up with friends. 

Posted by windsor | with no comments