Author Topic: BackGround Worker from hell  (Read 2038 times)

bachphi

  • Hero Member
  • *****
  • Posts: 671
    • View Profile
BackGround Worker from hell
« on: August 22, 2016, 10:44:56 AM »
Up until yesterday, I did not know who the heck the BackGround worker is, nor what exactly he's supposed to be doing... so say HELLo to my new BackGround worker. ;).

In my project, after scanning the barcode, I need to check if the SerialNumber exist in the SQL DB, if it is then display the data in the DataGridView , next call up the keypad and enter some number.  Since checking the DB does takes a few seconds, my display would freeze up before the keypad can appear. So I thought,  it would be nice if I can enter my number while its doing the check.
To avoid the problem of cross-threading call, I added a  BackGroundWorker to my form, start calling it with
Code: [Select]
        dgvData.DataSource = Nothing
        dgvData.Rows.Clear()
        BGW1.RunWorkerAsync()                           'Using BGW to check if Serial exist

This worker has 3 events associated with it: DoWork, ProgressChanged and RunWorkerCompleted. The DoWork will do the heavy lifting and the Progress or Completed will allow you to set the DataGridView from the original UI thread!!

Here is the code:

Code: [Select]
Private Sub BGW1_DoWork(sender As Object, e As ComponentModel.DoWorkEventArgs) Handles BGW1.DoWork
        If SQL.HasConnection = True Then
            SQL.RunQuery("SELECT * FROM TB01_DP_TestData WHERE [SerialNumber] = '" & StaSerialNumber & "'")
        End If     
End Sub

Private Sub BGW1_ProgressChanged(sender As Object, e As ComponentModel.ProgressChangedEventArgs) Handles BGW1.ProgressChanged
       
End Sub

Private Sub BGW1_RunWorkerCompleted(sender As Object, e As ComponentModel.RunWorkerCompletedEventArgs) Handles BGW1.RunWorkerCompleted
        If SQL.DS.Tables.Count > 0 Then                 'Returning from the call
            If SQL.DS.Tables(0).Rows.Count > 0 Then     'IF SerialNumber exist
                dgvData.DataSource = SQL.DS.Tables(0)
                'Label9.Text = SQL.DS.Tables(0).Rows(0).Item(2)
            Else
                'MsgBox("Not FOund")
            End If
        End If
End Sub
« Last Edit: August 22, 2016, 01:50:12 PM by bachphi »
===================================================
This is NOT alt.read.my.mind.
No such thing is sh^t-for-brains unless you are posting to alt.read.my.mind.
===================================================

bachphi

  • Hero Member
  • *****
  • Posts: 671
    • View Profile
Using Delegate method
« Reply #1 on: August 22, 2016, 12:29:53 PM »
Another approach besides using BackGround Worker is to start another thread and use Delegate method. It seems to be the official way of MS to deal with making thread safe calls. It worked for me as well.


Code: [Select]
dgvData.DataSource = Nothing
dgvData.Rows.Clear()
System.Threading.Tasks.Task.Factory.StartNew(Sub()
                                              CheckSerialInfo()
                                              End Sub)

...

Private Delegate Sub CheckSerialInfo_delegate(ByVal serial As String)
Private Sub CheckSerialInfo()

        If SQL.HasConnection = True Then   
            SQL.RunQuery("SELECT * FROM TB01_DP_TestData WHERE [SerialNumber] = '" & StaSerialNumber & "'")
            If SQL.DS.Tables.Count > 0 Then                 'Returning from the call
                If SQL.DS.Tables(0).Rows.Count > 0 Then     'IF SerialNumber exist
                    If Me.dgvData.InvokeRequired Then
                        Dim d As New CheckSerialInfo_delegate(AddressOf CheckSerialInfo)
                        Me.dgvData.BeginInvoke(d, {StaSerialNumber})
                    Else
                        Me.dgvData.DataSource = SQL.DS.Tables(0)
                    End If
                    'Label9.Text = SQL.DS.Tables(0).Rows(0).Item(2)
                Else
                    'MsgBox("Not FOund")
                End If
            End If
        End If
    End Sub


« Last Edit: August 22, 2016, 01:51:36 PM by bachphi »
===================================================
This is NOT alt.read.my.mind.
No such thing is sh^t-for-brains unless you are posting to alt.read.my.mind.
===================================================

bachphi

  • Hero Member
  • *****
  • Posts: 671
    • View Profile
Invoke or Not Invoke
« Reply #2 on: August 22, 2016, 12:34:57 PM »
The 3rd approach is not using the Delegate method, it seemed to be complicated with delegate this and delegate that for each call. Instead , just use invoke .


Code: [Select]
Private Sub CheckSerialInfo()
        If SQL.HasConnection = True Then   
           SQL.RunQuery("SELECT * FROM TB01_DP_TestData WHERE [SerialNumber] = '" & StaSerialNumber & "'")

            If SQL.DS.Tables.Count > 0 Then                 'Returning from the call
                If SQL.DS.Tables(0).Rows.Count > 0 Then     'IF SerialNumber exist
                    If Me.dgvData.InvokeRequired Then
                        Invoke(New MethodInvoker(Sub() Me.dgvData.DataSource = SQL.DS.Tables(0)))
                    Else
                        Me.dgvData.DataSource = SQL.DS.Tables(0)
                    End If
                    'Label9.Text = SQL.DS.Tables(0).Rows(0).Item(2)
                Else
                    'MsgBox("Not FOund")
                End If
            End If
        End If
    End Sub


« Last Edit: August 22, 2016, 01:52:06 PM by bachphi »
===================================================
This is NOT alt.read.my.mind.
No such thing is sh^t-for-brains unless you are posting to alt.read.my.mind.
===================================================