Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations TouchToneTommy on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Checking InvokeRequired three times in a function? 1

Status
Not open for further replies.

shaminda

Programmer
Jun 9, 2000
170
US
I have function in one of my vb.net 2003 called LoadUserDara. On and off my program started hanging inside the function. So I had to call this function from a different thread. Inside this function I had to check for InvokeRequied three times. Here is my code for the function:
Code:
Private Sub LoadUserData(ByVal DeltaPartNumber As String)
  Dim oBaseForm As New cBaseForm
        Dim Connection As SqlConnection = Nothing
        Dim sConnectStringSQL As String
        Dim _oReadINI As iReadINI.iReadINI
        Dim PATH_LOG_FILE As String
        Dim sWheelType As String

        Try

            _oReadINI = New iReadINI.iReadINI("TA0Config")
            sConnectStringSQL = _oReadINI.ReadINI("PokaYoke", "ConnectString", "")
            Connection = oBaseForm.GetConnection(sConnectStringSQL)
            'Log file    
            PATH_LOG_FILE = _oReadINI.ReadINI("PokaYoke", "PathLogFile", "")
            oError = New cError(True, True, False, True, True, True, PATH_LOG_FILE, "LotCtrlTA0")

            Application.DoEvents()

            'This will clear the styles from last load
            If DataGrid1.InvokeRequired Then
                Dim mi As New MethodInvoker(AddressOf ClearDataGridData)
                DataGrid1.Invoke(mi, Nothing)
            Else
                DataGrid1.TableStyles.Clear()
            End If


            sWheelType = Mid(DeltaPartNumber, 6, 3)
            Dim ds As DataSet
            Select Case sWheelType
                Case "SDB"
                    ds = SqlHelper.ExecuteDataset(Connection, CommandType.StoredProcedure, "spLoadUserDataMainSDB")
                Case "SDN"
                    ds = SqlHelper.ExecuteDataset(Connection, CommandType.StoredProcedure, "spLoadUserDataMainSDB")
                Case "SDP"
                    ds = SqlHelper.ExecuteDataset(Connection, CommandType.StoredProcedure, "spLoadUserDataMainSDB")
                Case "SEP"
                    ds = SqlHelper.ExecuteDataset(Connection, CommandType.StoredProcedure, "spLoadUserDataMainSDB")
                Case "TA0"
                    ds = SqlHelper.ExecuteDataset(Connection, CommandType.StoredProcedure, "spLoadUserDataMainSDB")
                Case "TE0"
                    ds = SqlHelper.ExecuteDataset(Connection, CommandType.StoredProcedure, "spLoadUserDataMainSDB")
            End Select


            'change column names
            ds.Tables(0).Columns("fdShortNumber").ColumnName = "Short Number"
            ds.Tables(0).Columns("fdPartNumber").ColumnName = "Part Number"
            'Change column widths
            Dim tsGridTableStyles As New DataGridTableStyle
            tsGridTableStyles.MappingName = ds.Tables(0).ToString()

            'Create GridColumnStyle objects for the grid tables

            Dim aCol0 As New DataGridEnableTextBoxColumn(1)
            Dim aCol1 As New DataGridEnableTextBoxColumn(2)
            Dim aCol2 As New DataGridEnableTextBoxColumn(3)
            Dim aCol3 As New DataGridEnableTextBoxColumn(4)
            Dim aCol4 As New DataGridEnableTextBoxColumn(5)
            Dim aCol5 As New DataGridEnableTextBoxColumn(6)
            Dim aCol6 As New DataGridEnableTextBoxColumn(7)
            Dim aCol7 As New DataGridEnableTextBoxColumn(8)
            Dim aCol8 As New DataGridEnableTextBoxColumn(9)

            'Column UserLoadId
            With aCol0
                .MappingName = "fdUserLoadId"
                .HeaderText = "ID"
                .Width = 30

            End With
            AddHandler aCol0.CheckCellEnabled, New DataGridEnableTextBoxColumn.EnableCellEventHandler(AddressOf SetEnableValues)

            'Column ShortNumber
            With aCol1
                .MappingName = "Short Number"
                .HeaderText = "SHORT #"
                .Width = 65
            End With
            'an EnableCell event handler
            AddHandler aCol1.CheckCellEnabled, New DataGridEnableTextBoxColumn.EnableCellEventHandler(AddressOf SetEnableValues)

            'Column PartNumber
            With aCol2
                .MappingName = "Part Number"
                .HeaderText = "PART NUMBER"
                .Width = 180
            End With
            'an EnableCell event handler
            AddHandler aCol2.CheckCellEnabled, New DataGridEnableTextBoxColumn.EnableCellEventHandler(AddressOf SetEnableValues)

            'Column Quantity
            With aCol3
                .MappingName = "fdQuantity"
                .HeaderText = "QUANTITY"
                .Width = 75
            End With
            'an EnableCell event handler
            AddHandler aCol3.CheckCellEnabled, New DataGridEnableTextBoxColumn.EnableCellEventHandler(AddressOf SetEnableValues)

            'Column Quantity
            With aCol4
                .MappingName = "fdCustDestination"
                .HeaderText = "DESTINATION"
                .Width = 85
            End With
            'an EnableCell event handler
            AddHandler aCol4.CheckCellEnabled, New DataGridEnableTextBoxColumn.EnableCellEventHandler(AddressOf SetEnableValues)

            'Column Ran Number
            With aCol5
                .MappingName = "fdRanNumber"
                .HeaderText = "RELEASE ORDER#"
                .Width = 120
            End With
            'an EnableCell event handler
            AddHandler aCol5.CheckCellEnabled, New DataGridEnableTextBoxColumn.EnableCellEventHandler(AddressOf SetEnableValues)

            'Column Vin Number
            With aCol6
                .MappingName = "fdVinNumber"
                .HeaderText = "SEQ#"
                .Width = 60
            End With
            'an EnableCell event handler
            AddHandler aCol6.CheckCellEnabled, New DataGridEnableTextBoxColumn.EnableCellEventHandler(AddressOf SetEnableValues)

            Application.DoEvents()

            'Column Counter
            With aCol7
                .MappingName = "fdCounter"
                .HeaderText = "COUNTER"
                .Width = 70
            End With
            'an EnableCell event handler
            AddHandler aCol7.CheckCellEnabled, New DataGridEnableTextBoxColumn.EnableCellEventHandler(AddressOf SetEnableValues)

            'Column Lot Status
            With aCol8
                .MappingName = "fdRackComplete"
                .HeaderText = "RACK STATUS"
                .Width = 90
            End With
            'an EnableCell event handler
            AddHandler aCol8.CheckCellEnabled, New DataGridEnableTextBoxColumn.EnableCellEventHandler(AddressOf SetEnableValues)

            'Add the grid column styles to the DataGrid's Column Styles Collection.
            With tsGridTableStyles.GridColumnStyles
                .Add(aCol0)
                .Add(aCol1)
                .Add(aCol2)
                .Add(aCol3)
                .Add(aCol4)
                .Add(aCol5)
                .Add(aCol6)
                .Add(aCol7)
                .Add(aCol8)
            End With
            'Add GridColumnStyles to the grid table styles.
            If DataGrid1.InvokeRequired Then
                Dim delAdd As New DelAddDataGridData(AddressOf AddDataGridData)
                Dim o() As Object = {tsGridTableStyles}
                DataGrid1.Invoke(delAdd, o)
            Else
                DataGrid1.TableStyles.Add(tsGridTableStyles)
            End If

            'Bind the DataGrid to the DataSet.Expand and navigate to first row.
            If ds.Tables(0).Rows.Count > 0 Then
                If DataGrid1.InvokeRequired Then
                    Dim delBind As New DelBindDataGridData(AddressOf BindDataGridData)
                    Dim o() As Object = {ds}
                    DataGrid1.Invoke(delBind, o)
                Else
                    With (DataGrid1)
                        .DataSource = ds.Tables(0)
                        .Expand(-1)
                        .NavigateTo(0, "tbUserLoad")
                    End With
                End If
            End If

            Application.DoEvents()

            tsGridTableStyles = Nothing
            aCol0.Dispose()
            aCol1.Dispose()
            aCol2.Dispose()
            aCol3.Dispose()
            aCol4.Dispose()
            aCol5.Dispose()
            aCol6.Dispose()
            aCol7.Dispose()
            aCol8.Dispose()

            ds.Dispose()
            ds = Nothing
            aCol0 = Nothing
            aCol1 = Nothing
            aCol2 = Nothing
            aCol3 = Nothing
            aCol4 = Nothing
            aCol5 = Nothing
            aCol6 = Nothing
            aCol7 = Nothing
            aCol8 = Nothing



        Catch ex As Exception
            Call oError.CheckError("LoadUserData", ex)

        Finally
            If Not Connection Is Nothing Then
                CType(Connection, IDisposable).Dispose()
            End If
            oBaseForm.Dispose()
            _oReadINI = Nothing
            oBaseForm = Nothing
        End Try
    End Sub

    Private Sub ClearDataGridData()
        Dim _oReadINI As iReadINI.iReadINI
        Dim PATH_LOG_FILE As String
        Try
            _oReadINI = New iReadINI.iReadINI("TA0Config")
            PATH_LOG_FILE = _oReadINI.ReadINI("PokaYoke", "PathLogFile", "")
            oError = New cError(True, True, False, True, True, True, PATH_LOG_FILE, "LotCtrlTA0")

            DataGrid1.TableStyles.Clear()
        Catch ex As Exception
            Call oError.CheckError("SetEnableValues", ex)
        Finally

            _oReadINI = Nothing
        End Try

    End Sub
    Private Sub AddDataGridData(ByVal tsGridTableStyles As DataGridTableStyle)
        Dim _oReadINI As iReadINI.iReadINI
        Dim PATH_LOG_FILE As String
        Try
            _oReadINI = New iReadINI.iReadINI("TA0Config")
            PATH_LOG_FILE = _oReadINI.ReadINI("PokaYoke", "PathLogFile", "")
            oError = New cError(True, True, False, True, True, True, PATH_LOG_FILE, "LotCtrlTA0")

            DataGrid1.TableStyles.Add(tsGridTableStyles)
        Catch ex As Exception
            Call oError.CheckError("SetEnableValues", ex)
        Finally
            _oReadINI = Nothing
        End Try

    End Sub
    Private Sub BindDataGridData(ByVal ds As DataSet)
        Dim _oReadINI As iReadINI.iReadINI
        Dim PATH_LOG_FILE As String
        Try
            _oReadINI = New iReadINI.iReadINI("TA0Config")
            PATH_LOG_FILE = _oReadINI.ReadINI("PokaYoke", "PathLogFile", "")
            oError = New cError(True, True, False, True, True, True, PATH_LOG_FILE, "LotCtrlTA0")

            With (DataGrid1)
                .DataSource = ds.Tables(0)
                .Expand(-1)
                .NavigateTo(0, "tbUserLoad")
            End With
        Catch ex As Exception
            Call oError.CheckError("SetEnableValues", ex)
        Finally
            _oReadINI = Nothing
        End Try
    End Sub
The question I have is, is this the best way to handle multithreading? Or is there a better way?
 
You could just do the thread check once, and run all of the code on the data grid's thread... That would simplify your code a bit, but if you have any process intensive or I/O wait code in there, the GUI may stop updating. Any time you interact with the GUI or any object with a GUI interface, you must be on the same thread that created it. One of those annoying limitations of GDI+. But any code that will consumer mass resources or hit I/O waits (disk, network, database access) you want off the GUI thread so they don't cause the app to stop responding.

In such cases, it is sometimes required to code as you have, where the bulk of the method is handled in a different thread and the calls to GUI objects is made thread safe. One thing I like doing though is to move any cross thread references into their own subs. It shouldn't effect anything performance wise, but it makes the code easier to follow (IMO). So I would move code like this:
Code:
                If DataGrid1.InvokeRequired Then
                    Dim delBind As New DelBindDataGridData(AddressOf BindDataGridData)
                    Dim o() As Object = {ds}
                    DataGrid1.Invoke(delBind, o)
                Else
                    With (DataGrid1)
                        .DataSource = ds.Tables(0)
                        .Expand(-1)
                        .NavigateTo(0, "tbUserLoad")
                    End With
                End If
into its own sub, then call that method from your larger method.

-Rick

VB.Net Forum forum796 forum855 ASP.NET Forum
[monkey]I believe in killer coding ninja monkeys.[monkey]
 
Thanks Rick for your help once again! My program doesn't freeze anymore.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top