Login | Register   
Twitter
RSS Feed
Download our iPhone app
TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
Browse DevX
Sign up for e-mail newsletters from DevX


advertisement
 

What's New in the Visual Studio 2005 Toolbox for Windows Applications? : Page 4

The toolbox for Windows Forms applications was already pretty rich in Visual Studio .NET 2003, but it will be even richer when the next version ships. In this article, I'll take you on a whistle-stop tour of the new controls slated for Windows Forms 2.0 to make writing code more productive and pleasant than ever.


advertisement
New Components for System Functions
As you saw in Figure 1, the Components tab of the Visual Studio 2005 toolbox sports a few new and interesting entries. Aside from the DataConnector component that I just discussed, two more entries catch the eye—the SerialPort and BackgroundWorker components.

With the SerialPort class, serial port communication finally arrives in .NET. Preceded by a free component available on GotDotNet and working in .NET 1.x applications, the SerialPort class represents any resources available through the serial port. You use this class to perform synchronous I/O over a port. In addition, a bunch of events are available to let you catch bytes, EOF characters received, or errors. You can also use the SerialPort class to gain access to pin and break states, and driver properties.

More importantly, you can wrap the functionality of the SerialPort class in an internal Stream object, accessible through the BaseStream property. In this way, you can pass it to any classes that can consume streams.

Visual Studio 2005 defines the SerialPort class in the System.IO.Ports namespace and you use it as follows.

SerialPort com = new SerialPort("COM1"); com.ReceivedEvent += new EventHandler(Received);

Note that the serial port components work well with virtual COM ports but it doesn't support USB ports. This is by design because USB is a hardware bus that only Windows device-drivers control. As such, it is not directly exposed to user-mode applications, including .NET applications.

Background Tasks
I would say nothing really new by stating that many commonly performed operations can take a long time to execute. Some operations normally cause the front-end of your application to hang until they complete and return. A prompt and responsive user interface is way better for all users and developers. The recipe to solve this issue is known: Run the lengthy operation on a background thread. In Windows Forms 1.x, the threading API made this task much more affordable than it was in Win32. In the .NET Framework 2.0, the BackgroundWorker class provides an even more convenient solution.

The BackgroundWorker class saves you from dirtying your hands with threads and provides watershed events where you know exactly what to do and how. One of the snags with direct thread handling is that you can't touch any UI control from within the secondary thread running the lengthy operation. No doubt this fact leads you to writing neater code; however, it raises trouble in the short run by forcing you to implement effective patterns. The BackgroundWorker class does much of this work for you. I'd be a liar if I said that you only need to write a little code on your own, but the good news is that the code you must write is clear, concise, and easy to understand. Let's take the sample code you can get from the MSDN online documentation, put it through its paces, and build a sample form that calculates a Fibonacci number with the usual set of bells and whistles of an asynchronous operation: toggle button, abort option, and progress bar.

Setting up a BackgroundWorker component is an overall simple procedure. You start the operation by calling the RunWorkerAsync method.

// Toggle the status of Start/Cancel buttons buttonStart.Enabled = false; buttonCancel.Enabled = true; // Get the value from the UpDown control numberToCompute = (int) numericUpDown1.Value; // Start the LENGTHY operation backgroundWorker1.RunWorkerAsync(numberToCompute);

The RunWorkerAsync method takes an object that represents the input parameter for the lengthy operation. Should you need to pass multiple values to the method, all of them must be grouped in a custom class. In the sample above, it just receives an integer that represents the value to compute in the Fibonacci series.

The default event of the BackgroundWorker class is DoWork and it's the place where the actual, potentially time-consuming work, is done. Here's a typical implementation of the event handler.



void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { BackgroundWorker worker; worker = (BackgroundWorker) sender; int num = (int) e.Argument; e.Result = ComputeFibonacci(num, worker, e); }

The handler retrieves the instance of the class and the argument passed to RunWorkerAsync and uses this data to prepare the call to the long-running method. The result of the computation is assigned to the Result property of the DoWorkEventArgs object. In this way, the result will be available to the application through the component's RunWorkerCompleted event.

You must also handle the RunWorkerCompleted event. It fires when the lengthy operation has completed. Note that this event handler runs in the primary thread so that you can safely and successfully access UI elements. While refreshing the user interface, you might want to check some state properties on the BackgroundWorker class. Here's an example:

if (e.Error != null) MessageBox.Show(e.Error.Message); else if (e.Cancelled) result.Text = "Operation aborted"; else result.Text = e.Result.ToString();

If your code detects an error, you show a message box. If the user aborts the operation, you reset the user interface; otherwise, you proceed consuming the results.

Interacting with a progress bar is easy too. You just have to write a handler for the ProgressChanged event. The handler receives the progress percentage that you retrieve and uses it to update your user interface. (This handler, in fact, runs within the UI thread.) The following code snippet demonstrates how to proceed with a Progress Bar control and a label.

void backgroundWorker1_ProgressChanged( object sender, ProgressChangedEventArgs e) { progressBar1.Value = e.ProgressPercentage; result.Text = String.Format( "Calculating... {0}% done.", e.ProgressPercentage); }

Figure 6 shows the sample application in action. Listing 1 contains the most important part of this code.

 
Figure 6: A form that executes a background operation.
You must design the method that implements the lengthy operation to support a progress bar, or any sort of similar UI widget. In fact, it is up to the method that performs the lengthy task to fire the ProgressChanged event whenever it reckons it useful and significant. Listing 2 presents the full implementation of the method that computes a Fibonacci number.

The ComputeFibonacci method calculates the value to report as the progress done on the operation and calls a method on the worker class-the ReportProgress method. This method greatly simplifies programming because of its simple prototype and the fact that it is exposed from the ubiquitous BackgroundWorker class. Use the CancelAsync method to abort a running operation.



Comment and Contribute

 

 

 

 

 


(Maximum characters: 1200). You have 1200 characters left.

 

 

Sitemap