Threading in a windows service????

WellsCarrie

Well-known member
Joined
Jul 12, 2005
Messages
95
Location
Arkansas
Programming Experience
5-10
Solved - Threading in a windows service????

:confused:
I have a file watcher service that picks up a file, reads some data from it, Puts the data on a word document, prints the document, and then moves the file to another directory.

If only one file is droped to the watched directory at a time every thing works great. However if more than one file gets dropped it boggs down taking 8 to 20 minutes to complete the process per file instead of the 4 for just one.)

Is this a threading issue? And if so how do I make my service properly thread and use enough processor power to complete the work in a reasonable time?

thanks!
 
Last edited:
Why don't you spawn a thread to perform the processing on the file so your main thread can get back to watching? You then just need to spawn a thread for each file.
 
I tried to that just wednesday afternoon. My problem is that I only know the proper file name while inside the "fsw1_Created" Sub. You can't pass values to delegates in v1.1 so how would you suggest I get the file name to the worker subs?

I've thought of using an application string array but I can't figure out how to prevent exponetal growth. Any ideas?

Additionaly I've set up an event log to record any exceptions that occur but when I run my “now shared” functions and subs it tells me “Can not refer to an instance of a class from within a shared method or shared member initializer without an explicit instance of the class.” What I can’t figure out is how to reference a class the shared function/sub is already an instance of.
 
Last edited:
With regards to passing info to your threads, just use a collection to store the values and have each thread remove it's data once it has retrieved it:
VB.NET:
    Private threadData As New Hashtable

    Private Sub StartThread()
        Dim t As New Threading.Thread(AddressOf ThreadStart)

        'Set the data for the new thread.
        Me.threadData.Add(t, "ThreadData")

        t.Start()
    End Sub

    Private Sub ThreadStart()
        'Get the data for this thread.
        Dim data As String = CStr(Me.threadData(Threading.Thread.CurrentThread))

        'Remove the data for this thread.
        Me.threadData.Remove(Threading.Thread.CurrentThread)

        MessageBox.Show(data)
    End Sub
As for your Shared members, they know nothing of instances of the class unless you specifically tell them about one. A Shared member should ALWAYS be qualified with the class name, not an instance variable. If you want a Shared member to manipulate an instance then you need to pass a reference to that instance as an argument.
 
If you use the sample above you'll want to make sure you use some kind of Mutex around calls to the hash table. But another approach is to create a class that has a member variable for the file name. The following example should make it clear:

VB.NET:
Module TestModule
    class PassDataToThread
        Public data As String
        Public Sub Funct()
            System.Console.WriteLine("You passed: " & data)
        End Sub
    End Class
    Public Sub Main
        Dim pdtt As New PassDataToThread()
        mpc.data = "My data"
        Dim thr As System.Threading.Thread = New System.Threading.Thread(AddressOf pdtt.Funct) 
        thr.Start() 
        thr.Join()
    End Sub
End Module

This might be a cleaner way of doing it, because it eliminates the need for Mutexes.
 
Thanks for the info!
For everyone's enlightenment the real problem was not proper threading.

Instead it was the way in which my service was cleaning up after itself. Although I was running a “.Kill” on all the Word apps the service could find running on my machine, the memory usage of each app instance was still being held. Thus after I had run 3 to 4 debug sessions the computer would have a good 45% to 75% minimum of the available memory in use by word applications I thought dead. Meaning it was not available for use by the process (basically a huge memory leak). I ended up reworking my entire design to reuse the initial word app created for every document I wanted to open and print.

I am now using a “timer elapsed” event. The event uses some IO objects to check the folder for the correct file type. When one or more is found it stops the timer and processes them (reusing the same word app instance for each cycle). Then it restarts the timer. I have been able to run up to 100 files in 10 to 15 minutes. It only takes this long because of the Print Queue, If I just open and save I’ve gotten a 100 files done in 2 to 3 minutes (this because of the speed of the AS400 database). This is acceptable, though, because it takes the Shipping floor 5 to 10 minutes to “wrap” a pallet. Thus the files to be printed (of which in reality there are only 2 per pallet) are done and waiting by the time the “wrapper” has completed its job. Additionally, there will be a printer for each Pallet Wrapping Station which means that only 2 prints will be happening in any 5 to 10 minute period.
 
Here's an analogy I've used before. Calling CloseMainWindow on a running process is like asking someone to leave the premises, while calling Kill is like grabbing them by the scruff of the neck and throwing them out. Killing a process gives it no opportunity to clean up after itself. If these are instances of Word that you have started yourself through automation then you should be cleaning them up yourself. Otherwise, at least call CloseMainWindow first to give the app a chance to clean up, then only call Kill if it refuses to close itself.
 
Back
Top