Threading a ShowDialog? - progress form.

M

Miro

I will try my best to ask this question correctly. I think in the end the
code will make more sence of what I am trying to accomplish. I am just not
sure of what to search for on the net.

I have a form that has a button. ( this form is a child form of a parent
form ( main form ).
Anway...in this child form I have a button, and if clicked a bunch of code
will get executed.
I would like to show a Progress Bar / form in modal/ShowDialog format when
this runs and slowely update the progress bar as each sub runs.

I cant just call the form with fStatus.ShowDialog() cause then all code
stops till this form is closed. So What I am trying is to somehow open this
form in a different thread - in ShowDialog format, so I can continue to run
my code, and as my code runs, update the progress bar on the new status form
created.
At the end, close the status form, and let the user continue on.
As the status form is open, the whole app is 'locked' because of showdialog,
until it is complete.

I hope this makes sence.

Below I have code that I think is in the right direction, but I am at a wall
as I have never done any thread processing.

Thanks for your help,

Miro


'==== some command button _click event on a current form. 'which is a child
form of a mdi form.
'Somewhere here change the icon to be hourglass

Dim fStatus As New frmStatus()

'im pulling code out of my butt for this next line here cause ive
never done this before
Dim Thread1 As New System.Threading.Thread(AddressOf
fStatus.ShowDialog)

Thread1.Start()

'pbStatus is a status bar / progress bar
fStatus.pbStatus.Value += 10 'Increment Push Button
System.Threading.Thread.Sleep(2000) 'Will Call some sub instead later

fStatus.pbStatus.Value += 10
System.Threading.Thread.Sleep(2000) 'Will Call some sub instead later
fStatus.pbStatus.Value += 10
System.Threading.Thread.Sleep(2000) 'Will Call some sub instead later

'Somewhere here change the icon to be pointer again.

'close the form
fStatus.Close()
'im assuming i have to close the thread too or something?
fStatus.Dispose()
'user should have access to the whole app again.

'==== end of some command button _click event
 
J

Jay B. Harlow

Miro,
Are you using VS 2005 (.NET 2.0) or VS 2002/2003 (.NET 1.x)?

..NET 2.0's new BackgroundWorker component makes this really easy!

For example create a new dialog from, put a BackgroundWorker object on it,
along with a ProgressBar.

Using the following code for the form.

Option Strict On
Option Explicit On

Imports System.ComponentModel
Imports System.Threading

Public Class LongProcessDialog

Protected Overrides Sub OnLoad(ByVal e As System.EventArgs)
MyBase.OnLoad(e)
BackgroundWorker1.RunWorkerAsync()
End Sub

Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object,
ByVal e As DoWorkEventArgs) Handles BackgroundWorker1.DoWork
For percentProgress As Integer = 1 To 100
Thread.Sleep(TimeSpan.FromSeconds(1.5))
BackgroundWorker1.ReportProgress(percentProgress)
Next
End Sub

Private Sub BackgroundWorker1_ProgressChanged(ByVal sender As Object,
ByVal e As ProgressChangedEventArgs) Handles
BackgroundWorker1.ProgressChanged
Me.ProgressBar1.Value = e.ProgressPercentage
End Sub

Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As Object,
ByVal e As RunWorkerCompletedEventArgs) Handles
BackgroundWorker1.RunWorkerCompleted
Close()
End Sub

End Class

The BackgroundWorker1_DoWork event is where all the real work (long running
process) is being done. Within it you call BackgroundWorker1.ReportProgress
to have the dialog update its controls.

The BackgroundWorker itself handles calling Control.Invoke where needed.

BackgroundWorker also supports passing a parameter to the background thread,
returning results (including exceptions) as well as cancelling the
background thread!

My Xml Export Sample, uses the BackgroundWorker within an Outlook form to
perform a long running process.

http://www.tsbradley.net/Samples/VSTO/Xml.Export.Sample.aspx
 
M

Miro

Im using vb express 2005

This is what i needed to get me started.

I will search the web and what I need for Background worker

From what I understand reading the code, I cannot have the code I require in
the "form", i have to move the sub calls to the "background worker" sub, and
call the origina subs in there.

Thanks much!

Miro
 
J

Jay B. Harlow

Miro,
From what I understand reading the code, I cannot have the code I require
in the "form",
It depends on what you mean by "form", do you mean your "main" form, or do
mean your "worker" form.

I would put all the subs in a "worker" form, this "worker" form would
contain a ProgressBar, BackgroundWorker component, plus any other controls
that may be needed (such as inputs, cancel buttons.

The "main" form would display the "worker" form:

' someplace one the "main" form
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
EventArgs) Handles Button1.Click
Using dialog As New WorkerDialog
dialog.ShowDialog()
End Using
End Sub

http://msdn2.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
 
M

Miro

I was trying to keep the sub calls in the Main form,
and somehow update the "worker form" from anywhere.

I thought it would be a lot easier to have a modal form but be able to keep
running the code from behind.

I was hoping to make a "generic" "working" form and have the same one called
from everywhere.
Example:
Sub A calls B calls C

Sub D calls B and E
where E calls F

Since B can be called from 2 different original subs' and I would like to
update a "differnet" / "or the same" worker form, I wanted the subs,
themselves take care of the worker form, rather than the worker form take
care of the subs'.

Miro
 
J

Jay B. Harlow

I thought it would be a lot easier to have a modal form but be able to
keep running the code from behind.
I agree, on the surface a modal form would appear be a lot easier. However
in practice I am sure you will find the BackgroundWorker component to be
significantly easier. Considering that all the "heavy lifting" has been done
for you. All you really need to do is insert your code in the DoWork event.
Occasionally you may want to, but don't need to, call the BackgroundWorker
..ReportProgress method.

I was hoping to make a "generic" "working" form and have the same one
called from everywhere.
Example:
Sub A calls B calls C

Sub D calls B and E
where E calls F

It sounds like a good use for inheritance.

WorkerForm is a base form that has the common routines (B) along with the
progress bar & background worker. The DoWork event handler would call an
overridable method DoWork.

AForm would inherit from WorkerForm overriding the DoWork method calling Sub
A.

DForm would inherit from WorkerForm overiding the DoWork method calling Sub
D.

Sub A would be in AForm, while Sub D would be in DForm.

I was trying to keep the sub calls in the Main form,
and somehow update the "worker form" from anywhere.
You should be able to use the instance of the Form from the Forms
collection. The caveat is you need to handle the DoWork event to get the
background started...

Personally I find it cleaner to encapsulate (one of the tenants of Object
Oriented development) the "worker" logic all in the "worker form"...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top