Threading Help...

ddivita

Member
Joined
May 7, 2008
Messages
19
Programming Experience
10+
I am writing an application that will require the use of threads. I am not entirely sure how to go about setting it up and know little about threading. I need to update my UI when a thread is finished processing and have the ability to cancel the entire process at anytime. I also do not want a new thread to start until the previous thread and process have completed. The image processing I am doing is quite intense and only one instance can run at a time. I have read about thread Pool, but it has been said not to use it if your process runs for a long time. Here is the flow of the piece I need to add threading to:

A collection of images as iList(ofT) - imageCollection
A progress indicator
A listView that will display the results for each images processed
A button on the form to cancel the process
There is an external application I need to call using the Process.Start() method. Unfortunately, I have to do it this way. The application is from a 3rd party vendor we use.
Pseudo Code:
VB.NET:
Public  sub ProcessImages()
	For each image as ImageObject in imageCollection 
		‘Add this process to a thread
		ProcessWorker(image)
		When ProcessWorker is complete Update the ListView and Progress bar
	Next
End Sub

Private Sub ProcessWorker(image as ImageObject)
	Dim imageProcess as new Process = Process.Start(“theAppToRun”,image.name)	
imageProcess.start()
	‘This line usually hangs the whole system so I usually comment it out	
‘imagePorcess.WaitForExit

End Sub	
	

Private Sub btnCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancel.Click
        
KillAllProcessesAndThreads

    End Sub
 
Last edited by a moderator:
It looks like you're wanting to have your main app simply call another app to actually process the images. Doing it this way will mean that your main app will simply be sitting there waiting for the other app to finish it's current image so if you cancel the processing, the other app will still finish that image.

If you want the image processing to happen in just 1 app, you'll have all the control you need. Look into the BackgroundWorker control (it's in the toolbox) for this.

What all are the requirements for this?
 
I have my main app and the image processing app. The main app controls image albums. Each album may contain several images. When the user clicks a process button, the app will begin processing each album and the images in it. For example:

VB.NET:
Album 1
     Image 1
     Image 2
     Image 3

Album 2
     Image 1
     Image 2
     Image 3

So when they click the process images button it will cycle through each album and process the images. Each album needs to be processed individually. They cannot be process at the same time. So I need to loop through the albums and grab the collection of image and their paths. The images are passed to the image processing app through command arguments. Here is how it would look:

VB.NET:
For each album as AlbumObject in iList(of albumObject)
     ProcessImages(album.ImageCollection)
    
Next

VB.NET:
Sub ProcessImages(images as iList(of ImageObject))
     'the code here to create image string of paths

     dim imagePorcess as Process = Process.Start("theEXEToLoad",imagePathsString)
     
    'After the process has finished, update my UI.
End Sub

My dilemma is not starting a new process until the previous one has finished. also, if the user cancels the entire process I want whatever image process is running to be stopped. I do not want it to finish processing. Does this help?

Thanks

Daniel
 
Got it to work. Posting code...

Thank you for the worker process idea. Worked great. Here is the code:
VB.NET:
Public Class PorcessImages

    Private _project As ProjectObject = Nothing
    Private _Process As Process = Nothing
    
    Private Sub btnCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancel.Click

        Dim CancelResult As DialogResult = MessageBox.Show("Are you sure you want to cancle the image stitching and upload porcess?", "Cancel Stitching and Upload", MessageBoxButtons.YesNo)
        If CancelResult = Windows.Forms.DialogResult.Yes Then
            workerMain.CancelAsync()
            If Not Process.HasExited Then
                Me.Process.Kill()
            End If
            Me.Close()
        End If

    End Sub

   
    Private Delegate Sub SetListView(ByVal image As imageObject)

    Private Sub UpdateListView(ByVal image As imageObject)
        'Method to update my listviewItems or other porgress indicators
		
    End If


    End Sub

    Private Sub Process_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Me.btnClose.Enabled = False

    End Sub

    Private Sub processiMages()
     	 
		
            workerMain.WorkerSupportsCancellation = True
            workerMain.WorkerReportsProgress = True
            workerMain.RunWorkerAsync(Project)
        End If

    End Sub
    

   
    


    Private Sub Process_Shown(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Shown
        processiMages()
    End Sub

    Private Sub workerMain_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles workerMain.DoWork
        Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
      
        ' Assign the result of the computation
        ' to the Result property of the DoWorkEventArgs
        ' object. This is will be available to the 
        ' RunWorkerCompleted eventhandler.
        ProcessQue(e.Argument, worker, e)


    End Sub
    private Sub ProcessQue(ByVal panoramaProject As ProjectObject, ByVal worker As BackgroundWorker, ByVal e As DoWorkEventArgs)

        If worker.CancellationPending Then
            e.Cancel = True
        Else

            

            For Each image As ImageObject In Project.Albums

                If Not Me.workerMain.CancellationPending Then
                    _Process = Process.Start("theApp","theArgs")
		    _process.WaitForExit
		    
		    'This line is needed if we cancel the porcess mid stream
                    If Not Me.workerMain.CancellationPending Then
                        Me.Invoke(New SetListView(AddressOf UpdateListView), image)
                    End If

                Else
                    e.Cancel = True
                    Exit For
                End If
            Next
        End If
    End Sub

    Private Sub workerMain_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles workerMain.ProgressChanged
        Me.progressPanoramaStatus.Value = e.ProgressPercentage
    End Sub

Public Property Project() As ProjectObject
        Get
            Return _project
        End Get
        Set(ByVal value As ProjectObject)
            _project = value
        End Set
    End Property
End Class
 
There is also the ReportProgress method, you can pass anything via userState parameter here, the ProgressChanged event is raised on UI-thread so you don't need to make thread-safe delegate calls.
 
How would I use the ProgressChanged to send the changes to my listview? Is that possible? Also, do you know of a way I could create a CPU usage monitor while the process is running. I would want to target the image processing process, if possible. I tried it using delegates, but it didn't look very good. I used a progress bar and it was really jumpy. Do you have any ideas? Thanks

Daniel
 
You just call ReportProgress method, passing the data of your choice, and handle the ProgressChanged event.
 
Since i am using the process.waitforexit, the cpu progress would never get upadted until after that event. I tired using this:

while not process.hasexited
'update the cpu code
end

Would I do something like that?
 
I figured out using the timer control how to display the CPU usage. Basically you add a timer, performace , and progress bar to your form. doublt click the timer control to add the event to your code beind. Inside the event update the progress bar with the performanceControl.nextvalue. When I get a chance I will post the actual code. THanks

Daniel
 
Back
Top