Basic Threading question...

K

KC

Hey,

I'm trying to implement a cancel button in my app (this is after the bulk of
the program has been built). To do this I, of course, need to use a thread
to run the time consuming method while the UI continues on it's merry way. I
created a basic thread just as an initial test and I half expected it to
crash - and it did. My problem is I don't understand why and that's making
it hard to debug.

The whole thing crashes (I get the old 'object reference not set to an
instance of an object' error) after the method completes. The method that
I'm threading pulls data off a website, crunches some numbers, puts the
results in a datatable that is part of a dataset that is bound to a
datagrid.

Is it because I'm trying to update a control (which was created in the UI
thread)? That's the blank spot for me. I don't know what's suppose to happen
when my method/thread finishes.

I'm reading
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnadvnet/html/vbnet09272002.asp
about background processes but my methods and functions are built and use a
lot of info from the UI. Trying to separate them into a 'worker' class looks
problematic. Ideas? Links to simpler way of implementing a cancel button?
 
K

Ken Tucker [MVP]

Hi,

Post some code

Ken
-----------------
Hey,

I'm trying to implement a cancel button in my app (this is after the bulk of
the program has been built). To do this I, of course, need to use a thread
to run the time consuming method while the UI continues on it's merry way. I
created a basic thread just as an initial test and I half expected it to
crash - and it did. My problem is I don't understand why and that's making
it hard to debug.

The whole thing crashes (I get the old 'object reference not set to an
instance of an object' error) after the method completes. The method that
I'm threading pulls data off a website, crunches some numbers, puts the
results in a datatable that is part of a dataset that is bound to a
datagrid.

Is it because I'm trying to update a control (which was created in the UI
thread)? That's the blank spot for me. I don't know what's suppose to happen
when my method/thread finishes.

I'm reading
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnadvnet/html/vbnet09272002.asp
about background processes but my methods and functions are built and use a
lot of info from the UI. Trying to separate them into a 'worker' class looks
problematic. Ideas? Links to simpler way of implementing a cancel button?
 
K

KC

I was hoping you wouldn't ask that. Anyway, here are the essentials...

This first routine is from my run button. I declare a thread, set my cancel
variable (which the second routine uses), bind the table to a grid, create
and run the thread...

Private Sub butRunTrunk_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles butRunTrunk.Click
Dim t As Thread
cancelOperation = False 'set cancel operation switch
DataGrid10.SetDataBinding(germany, "TrunkBH")
t = New Thread(AddressOf trunkBHusage)
t.Start()
End Sub

This is the routine that is run in the thread. It very big and I just
included the part at the end where things come apart. I use to have the
binding part at the end of the routine, but I got an error that said
'Controls created on one thread cannot be parented to a control on a
different thread.' So I moved it to a point before the thread. That's where
I am now.

<MethodImpl(MethodImplOptions.Synchronized)> _
Private Sub trunkBHusage()

Try

[... lots of stuff that works ok...]

'Create columns
StatusBar1.Panels(0).Text = "Building datatable..."
If dt.Columns.Count = 0 Then
For x = 0 To UBound(trkColumn, 1)
dc = New DataColumn 'Create the first column
dc.DataType = System.Type.GetType(trkColumn(x, 1)) 'set
the data type
dc.ColumnName = trkColumn(x, 0) 'give the column a name
dc.ReadOnly = True 'make the column read only
dc.Unique = False 'column elements do not have to be
unique
dt.Columns.Add(dc) 'add the column to the table
created earlier
Next
End If

'insert data to table
For Each hkey In hPeakEr.Keys
junk = hkey.ToString.Split(New [Char]() {"@"c})

dr = dt.NewRow()
dr(0) = hMTX(hkey) 'MTX
dr(1) = junk(1) 'Trunk/BSC
dr(2) = hPeakBH(hkey).ToString 'Busy Hour
dr(3) = CDbl(hPeakEr(hkey)) 'Peak Erlangs
dt.Rows.Add(dr)
Next
StatusBar1.Panels(0).Text = "Table built..."

If dt.Rows.Count = 0 Then
StatusBar1.Panels(0).Text = "No 'SBS' trunks found for the
given MTX(s)."
Else
StatusBar1.Panels(0).Text = "Trunk BH Usage Done!"
End If

StatusBar1.Panels(0).Text = "Housekeeping..."
pbTUoverall.Value = 0
pbTUdaily.Value = 0
trkMenu.Enabled = True
butExpTrk.Enabled = True
elapsedTime(False)

Catch ex As Exception
' Let the user know what went wrong.
'MessageBox.Show(ex.Message)
errorMessages = ex.Message + vbCrLf + "subroutine: trunkBHusage"
+ vbCrLf + _
"Last status message: " + StatusBar1.Panels(0).Text + _
vbCrLf + Now.ToString + vbCrLf + vbCrLf
StatusBar1.Panels(0).Text = "See error log."
End Try

End Sub
 
K

Ken Tucker [MVP]

Hi,

You are probably better off using a delegates to execute a method
asynchronously than a thread. Here is an article from the msdn magazine
that shows how.

http://msdn.microsoft.com/msdnmag/issues/04/05/BasicInstincts/

Ken
-----------------------
I was hoping you wouldn't ask that. Anyway, here are the essentials...

This first routine is from my run button. I declare a thread, set my cancel
variable (which the second routine uses), bind the table to a grid, create
and run the thread...

Private Sub butRunTrunk_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles butRunTrunk.Click
Dim t As Thread
cancelOperation = False 'set cancel operation switch
DataGrid10.SetDataBinding(germany, "TrunkBH")
t = New Thread(AddressOf trunkBHusage)
t.Start()
End Sub

This is the routine that is run in the thread. It very big and I just
included the part at the end where things come apart. I use to have the
binding part at the end of the routine, but I got an error that said
'Controls created on one thread cannot be parented to a control on a
different thread.' So I moved it to a point before the thread. That's where
I am now.

<MethodImpl(MethodImplOptions.Synchronized)> _
Private Sub trunkBHusage()

Try

[... lots of stuff that works ok...]

'Create columns
StatusBar1.Panels(0).Text = "Building datatable..."
If dt.Columns.Count = 0 Then
For x = 0 To UBound(trkColumn, 1)
dc = New DataColumn 'Create the first column
dc.DataType = System.Type.GetType(trkColumn(x, 1)) 'set
the data type
dc.ColumnName = trkColumn(x, 0) 'give the column a name
dc.ReadOnly = True 'make the column read only
dc.Unique = False 'column elements do not have to be
unique
dt.Columns.Add(dc) 'add the column to the table
created earlier
Next
End If

'insert data to table
For Each hkey In hPeakEr.Keys
junk = hkey.ToString.Split(New [Char]() {"@"c})

dr = dt.NewRow()
dr(0) = hMTX(hkey) 'MTX
dr(1) = junk(1) 'Trunk/BSC
dr(2) = hPeakBH(hkey).ToString 'Busy Hour
dr(3) = CDbl(hPeakEr(hkey)) 'Peak Erlangs
dt.Rows.Add(dr)
Next
StatusBar1.Panels(0).Text = "Table built..."

If dt.Rows.Count = 0 Then
StatusBar1.Panels(0).Text = "No 'SBS' trunks found for the
given MTX(s)."
Else
StatusBar1.Panels(0).Text = "Trunk BH Usage Done!"
End If

StatusBar1.Panels(0).Text = "Housekeeping..."
pbTUoverall.Value = 0
pbTUdaily.Value = 0
trkMenu.Enabled = True
butExpTrk.Enabled = True
elapsedTime(False)

Catch ex As Exception
' Let the user know what went wrong.
'MessageBox.Show(ex.Message)
errorMessages = ex.Message + vbCrLf + "subroutine: trunkBHusage"
+ vbCrLf + _
"Last status message: " + StatusBar1.Panels(0).Text + _
vbCrLf + Now.ToString + vbCrLf + vbCrLf
StatusBar1.Panels(0).Text = "See error log."
End Try

End Sub
 

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

Similar Threads

invoking on the UI thread 5
VB.net and threading 4
Multi Threading question 2
basic threading question 2
Threading Question - Newbie 3
Basic Threading question 19
Threading 7
Starting a Thread takes too long 25

Top