Programming Windows Services with Microsoft Visual Basic 2008 : Extending the Threading Model

10/15/2013 7:23:16 PM

1. Extending the Threading Model

At this point, we have created a multithreaded service by adding a worker thread. However, we are currently limited to one worker thread. We’re going to change that now.

We have a few ways to resolve the fact that we’re using only one worker thread. A couple of factors affect what we decide to do. First, we need to consider the requirements of the problem we are trying to solve. Currently we’re polling a file location to determine whether any .txt files exist and, if they do, reacting to that information.

To determine the threading model we need, we have to ask several questions:

  • Can we monitor more than one file folder?

  • Can we monitor more than one file type per folder?

  • Can we move files of diffent types to different output folders?

  • Do we want to move more than one file at a time, per type, per folder?

Monitoring More Than One Folder

If we were going to monitor the same type of files but have more than one folder, monitoring them all by using one thread wouldn’t make much sense. The framework that we have designed allows our service to have multiple threads, all of which process one file type each.

Currently we have one folder and one file type: .txt. We also have one worker thread. However, we could easily create an array, a collection of threads, all of which read from a separate folder simultaneously. However, we need to fix a few things to make this work:

  • We need to add string resources for each folder being monitored.

  • We need to modify <ThreadFunc> to accept a parameter that would specify the folder location so that each thread monitors the proper folder.

  • We need to modify the class to create a collection of threads instead of a single worker thread.

  • <OnPause>, <OnContinue>, and <OnStop> stay the same because each thread already knows how to pause, continue, and stop based on the code already available.

Monitoring More Than One File Type Per Folder

You may decide that not only do you have multiple file folders, but that you also have multiple file types. Each file type can be processed differently, even though they come frome the same initial incoming folder.

For this scenario we need to make some more changes to the code:

  • We need to update the data passed to the thread so that both the Incoming folder and file type are monitored for, or a list of file types is monitored for. This most likely means passing in a structure or class with the information we need.

  • We need also need to update the <ThreadFunc> method to pass a new array of file type wild cards to the <GetFiles> call—which is only looking for .txt at this point.

Outputting to More Than One Folder

You could decide that you want each file type to be processed or sent to a different output folder. This has the following requirements:

  • Again we need to update the resource strings to have a list of possible output paths.

  • We need to update the <ThreadFunc> method to take a parameter indicating where to move the file to instead of the current parameter setting which is the OutgoingPath resource.

Processing More Than One File Type Per Folder

In the final modification, we are going to create multiple threads per incoming folder. This means that not only can we read from the same folder with multiple threads, but we can output to multiple folders. Each thread has to be configured with the incoming folder. Multiple threads can share the same file type to monitor for. If the threads are pointing to the same file type, we want to avoid having multiple threads monitor the same folder, because of issues with synchronization. However, when it comes to an output folder, we can share a single output folder among multiple threads, each thread writes differently named files, with different file types, so there is no need for synchronization.

When Complexity Steps In

One scenario is complex: multiple threads per file type, per folder. This means that more than one thread would be told to monitor a given folder. The problem is that there is no way for one thread to know that another thread is actively processing a given file. This might cause the service to have a large number of errors, which would waste CPU cycles—or you would spend more time with thread contention and failures than you would processing anything useful.

How do we get around this? In reality we don’t have many options. Any option that allows more than one thread at a time to process (or in this case, move) files will inadvertently end up fighting with another thread. This means that we either accept having a single thread per file type, per folder, or we create a master worker thread that looks for all files on the disk and then places the files into a queue shared between the producer thread and the consumer threads.

Although this is definitely possible, you always want to ensure that you don’t add too much complexity to your service just to be able to have more than one thread. If you only have a very low volume of files, this solution might not be worth the complexity or the processing overhead.

2. Adding a FileWorker Class

The threads need access to the parameters and properties of file locations and file types. To simplify this process, we’ll create a class that we’ll use to create an instance of the worker thread. This class will contain all the functionality and properties we need, and we won’t have to add all the direct functionality to the service. You will also be able to reuse this functionality in other applications that you design.

Designing a New Class File

Add a new class file to the Tutorials project and call it FileWorker. Then add the following imports to the top of the class definition, as shown in Listing 1.

Listing 1. Add the file require imports.
Imports System.Resources
Imports System.IO
Imports System.Text
Imports System.Threading

Adding a Constructor

Next we want to add a constructor. The constructor can be blank for now, as shown in Listing 2.

Listing 2. Add a blank constructor to the new class.
Public Sub New()
End Sub

Adding a Worker Thread

Now we want to add a single worker thread to the class, as shown in Listing 3. Later on we will have more than one worker thread.

Listing 3. Add the following thread to the new class.
Private m_WorkerThread As Thread = Nothing

Now we need to add a property that grants access to the worker thread so that we can join the thread from outside the class, as shown in Listing 4.

Listing 4. Expose the thread by adding a property.
Public ReadOnly Property WorkerThread() as Thread
Return m_WorkerThread
End Get
End Property

We use the ReadOnly accessor because we don’t want users to be able to set this value; we only want them to be able read it.

Adding the Worker Thread Function

Because we will be replicating most of the functionality of the current service <ThreadFunc>, you can copy and paste it from the Tutorials.vb file into the FileWorker class file. We will not modify the function.

Adding the Thread Action State

Similar to the service class, we need to be able to tell the worker class when to pause, continue, or stop. Add a class file and call it threadactionstate.vb. Copy the ThreadActionState structure from the tutorials.vb and paste it into the new threadactionstate.vb class file.

We are going to change the Thread Action State from a structure to a class. We need to do this because we will be passing a reference to our Thread Action State shared variable to the FileWorker class instances. Remember to comment out the version that currently exists in the Tutorials service class, unless you have already removed it.

As shown in Listing 5, create a local reference in the FileWorker class.

Listing 5. Define the following thread state variable.
Private m_ThreadAction As ThreadActionState

Adding a WriteLogEvent

Copy the WriteLogEvent method from the Service class to the FileWorker class. Although we could copy the event to our modService file and make it publicly accessible, we are going to create a self-contained reusable class.

Adding Our <Start> Method

The last thing we need to do now is to add our <Start> method. This method will be used to start the worker process <ThreadFunc> in each instance of our FileWorker class.

Listing 6. Create the following Start method.
Public Sub Start()
m_WorkerThread = New Thread(AddressOf ThreadFunc)
m_WorkerThread.Priority = ThreadPriority.Normal
m_WorkerThread.IsBackground = True
End Sub
  •  Programming Windows Services with Microsoft Visual Basic 2008 : Writing a New Thread Method, Monitoring with Multiple Threads
  •  The HP Virtual Server Environment : Example nPartition Management Scenario (part 4) - Rebooting and Booting nPartitions
  •  The HP Virtual Server Environment : Example nPartition Management Scenario (part 3) - Creating a new nPartition
  •  The HP Virtual Server Environment : Example nPartition Management Scenario (part 2) - Viewing the Complex after Installing Hardware, Extending the Existing nPartition
  •  The HP Virtual Server Environment : Example nPartition Management Scenario (part 1) - Viewing the Configuration of an nPartition Complex
  •  The HP Virtual Server Environment : nPartition Management Paradigms (part 2) - Remote Management via an nPartition Paradigm, Remote Management via the MP Paradigm
  •  The HP Virtual Server Environment : nPartition Management Paradigms (part 1) - Local nPartition Management Paradigm
  •  The HP Virtual Server Environment : nPartition Servers - Data Maintained by the Management Processor
  •  The HP Virtual Server Environment : HP nPartition Server Overview
  •  The HP Virtual Server Environment : Combining Partitioning Solutions, Independent Software Vendor Support
    Video tutorials
    - How To Install Windows 8

    - How To Install Windows Server 2012

    - How To Install Windows Server 2012 On VirtualBox

    - How To Disable Windows 8 Metro UI

    - How To Install Windows Store Apps From Windows 8 Classic Desktop

    - How To Disable Windows Update in Windows 8

    - How To Disable Windows 8 Metro UI

    - How To Add Widgets To Windows 8 Lock Screen

    - How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010
    programming4us programming4us
    Top 10
    Free Mobile And Desktop Apps For Accessing Restricted Websites
    MASERATI QUATTROPORTE; DIESEL : Lure of Italian limos
    TOYOTA CAMRY 2; 2.5 : Camry now more comely
    KIA SORENTO 2.2CRDi : Fuel-sipping slugger
    How To Setup, Password Protect & Encrypt Wireless Internet Connection
    Emulate And Run iPad Apps On Windows, Mac OS X & Linux With iPadian
    Backup & Restore Game Progress From Any Game With SaveGameProgress
    Generate A Facebook Timeline Cover Using A Free App
    New App for Women ‘Remix’ Offers Fashion Advice & Style Tips
    SG50 Ferrari F12berlinetta : Prancing Horse for Lion City's 50th
    Popular Tags
    Video Tutorail Microsoft Access Microsoft Excel Microsoft OneNote Microsoft PowerPoint Microsoft Project Microsoft Visio Microsoft Word Active Directory Exchange Server Sharepoint Sql Server Windows Server 2008 Windows Server 2012 Windows 7 Windows 8 Adobe Flash Professional Dreamweaver Adobe Illustrator Adobe Photoshop CorelDRAW X5 CorelDraw 10 windows Phone 7 windows Phone 8 Iphone