For most application developers, the core difference between Microsoft .NET applications and Visual Basic (VB) applications lies in their multitasking support. Unlike VB applications, .NET applications are oriented toward shared data and collaborative work environments. With .NET applications, developers can perform more than one task at a time—something that traditional VB applications don't support. If a VB 6.0 application starts processing a large data file, it stops everything else. The most developers can do is call the DoEvents function so that the OS can come up for air. The DoEvents function is the closest VB has come to multitasking; the function stops an application’s processing to see whether the OS sent any event messages to process.

Languages such as Visual C++ (VC++) have always supported multithreading (i.e., the technology that makes multitasking possible), but historically they typically haven't been application developers’ first choice. With VC++, you can create some killer applications—applications that you just can't create with a single-threaded language such as VB.

Microsoft has added multithreading, native calls to system APIs, and other enterprise features to the Common Language Runtime (CLR) to make the .NET languages first class. CLR lets .NET applications not only spawn multiple threads but also natively support multithreaded operations. Having components that can be safely and simultaneously called by multiple threads is what makes components that run under multithreaded hosts (e.g., Microsoft IIS) highly scalable.

A worker thread in an application lets users work with an application while a computation, file transfer, or another extended activity occurs in the background. Spawning worker threads requires developers to write code that takes advantage of multiple threads. Let's look at how you can add multiple threads to an application.

Creating a second thread in .NET languages is deceptively simple. You just need to create a System.Threading.Thread object. To begin, you must first create a System.Threading.ThreadStart delegate. The ThreadStart delegate takes the address of a method. The method might be part of the current class or associated with an instance of an alternative class. The delegate class lets the OS pass the address of a specified object method to a new thread, which, in turn, can call that method. The result is an instance of the ThreadStart object, which is passed to the Thread class constructor. You can then add data and properties to the Thread class instance, which will run as a worker thread when you call the thread's Start method. For more information about the ThreadStart delegate and Thread object, see the Microsoft Developer Network (MSDN) Library ( ).

After you assign the starting class and add data and properties, the thread doesn't automatically begin processing. To start the new thread, you need to call the Start method; to stop the thread, you call the Stop method. If you look at all the members of the Thread class, you'll see that the class supports the ability to not only start and stop a thread but also query a thread to determine whether it's still running, pause a thread if too many system resources are in use, and perform a variety of other thread-management functions.

However, these Thread class methods are the tip of the multithreaded-programming iceberg. The simplicity of using these methods gives way to less visible, larger problems associated with coordinating multiple threads in a multithreaded application. The complexity of using a language such as VC++ to develop applications is partly due to the language's syntax, the large set of multithreading classes with which to work, and the challenges associated with managing threads. Although the .NET Framework's languages simplify access to multithreading classes, constructing threads that behave correctly requires additional consideration in the design stage.

With that thought, let's discuss the use of new .NET tools, such as Visual Studio .NET. The general consensus is that these tools will make development faster, better, and cheaper. Although you can, no doubt, create better applications, keep in mind two caveats to the "faster, better, and cheaper" mantra. First, faster, better, and cheaper" depends on where you start. Second, "better" often comes at the expense of "faster" and "cheaper." Thus, although the .NET tools support a better development environment for enterprise applications, those applications might require a greater design commitment from developers. The application that a C++ developer can already build better might now get built faster and cheaper with Visual C# .NET. However, faster and cheaper might not be feasible for an experienced developer who, for the first time, is creating a true multithreaded application.