Query database in background thread

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • JC Voon

    #1

    Query database in background thread

    Hi All:

    I'm new in Threading and Web Services, can someone please verify my
    code, i'm not sure whether this is the correct way, althought it is
    partially work, but some time it will raise exception at FillDatatable
    dr.AcceptChange s, and also the XTraGridControl will not response when
    click on the column header to do sorting and filtering.

    What i'm trying to do is very simple, i just want to retrieve a very
    large table from web service and show it on the GridControl, the query
    will be execute in the background thread, so that user is able to
    scroll, filter, sort the result on the gridcontrol while the query is
    execute in the background


    Here is the code:

    edtSQL - a multiline text box to enter SQL statement
    edtKeyFields - a text box to enter the key fields of the SQL statement
    GridControl - I use developer XTraGrid control
    btnFillData - Button control
    btnStopFill - Button Control
    DataAccessWS.Da taAccessService Wse - A web service

    Private QueryThread As Thread
    Private Delegate Sub FillDataTableDe legate(ByVal table As DataTable)
    Private bFilling As Boolean


    ' when use click this button the background thread will start
    ' filling data to grid's datasource
    Private Sub btnFillData_Cli ck(ByVal sender As System.Object, ByVal e
    As System.EventArg s) Handles btnFillData.Cli ck
    Dim proxy As DataAccessWS.Da taAccessService Wse = New
    DataAccessWS.Da taAccessService Wse

    Me.ProgressBar1 .Step = 1
    Me.ProgressBar1 .Minimum = 0
    ' call the web method to calculate number of row will be return
    ' by the SQL statement
    Me.ProgressBar1 .Maximum = CInt(proxy.Exec uteScalar("SELE CT
    Count(*) FROM (" & edtSQL.Text & ") as tem"))

    GridControl3.Da taSource = Nothing
    GridView3.Colum ns.Clear()
    QueryThread = Nothing

    QueryThread = New Thread(AddressO f QueryDataBase)
    QueryThread.IsB ackground = True
    QueryThread.Nam e = "QueryThrea d"
    QueryThread.Sta rt()
    End Sub

    ' Sub routine used by the Background thread to query database
    Public Sub QueryDataBase()
    Dim proxy As DataAccessWS.Da taAccessService Wse = New
    DataAccessWS.Da taAccessService Wse
    Dim doc As XmlDocument
    Dim xn As XmlNode
    Dim dt As DataTable = New DataTable

    If GridControl3.Da taSource Is Nothing Then
    ' Call the web method to retrieve first page of record
    ' param1=SQL statement, param2=filter criteria,
    ' param3=key field, param4=Page size
    xn = proxy.RetrieveF irstPageRecord( edtSQL.Text, "",
    edtKeyFields.Te xt, 100)
    doc = XMLNodeToXMLDoc ument(xn)
    LoadDataTableFr omXMLDocument(d t, doc)

    ' Is is correct to create New FillDataTableDe legate each time
    ' the BeginInvoke is call ?
    Me.BeginInvoke( New FillDataTableDe legate(AddressO f
    FillDatatable), New Object() {dt})
    End If

    While True
    ' wait until FillDatatable completed
    While bFilling
    ' Is it ok to put this line in the thread function ?
    Application.DoE vents()
    End While

    xn = Nothing
    With DirectCast(Grid Control3.DataSo urce, DataTable)
    If .Rows.Count > 0 Then
    ' Call the web method to retrieve next page of record
    ' param1=Last row in current page, param2=SQL
    ' statement, param3=filter criteria, param4=key field
    ' param5=Page size
    xn =
    proxy.RetrieveN extPageRecord(S aveDataRowAsXML Document(.Rows( .Rows.Count
    - 1)), edtSQL.Text, "", edtKeyFields.Te xt, 100)
    End If
    End With

    If Not xn Is Nothing Then
    dt.Clear()
    doc = XMLNodeToXMLDoc ument(xn)
    LoadDataTableFr omXMLDocument(d t, doc)

    ' if RetrieveNextPag eRecord return 0 row means Eof
    If dt.Rows.Count > 0 Then
    Me.BeginInvoke( New FillDataTableDe legate(AddressO f
    FillDatatable), New Object() {dt})
    Else
    Exit While
    End If

    If QueryThread.Thr eadState = ThreadState.Abo rted Then
    Exit While
    End If
    End If
    End While
    End Sub

    ' Sub routine that is to be executed on Form's thread
    Public Sub FillDatatable(B yVal table As DataTable)
    bFilling = True
    If GridControl3.Da taSource Is Nothing Then
    GridControl3.Da taSource = table.Copy
    Me.ProgressBar1 .Value = table.Rows.Coun t
    Else
    Dim dr As DataRow

    With DirectCast(Grid Control3.DataSo urce, DataTable)
    .BeginLoadData( )
    For i As Integer = 0 To table.Rows.Coun t - 1
    dr = .NewRow
    CopyDataRow(tab le.Rows(i), dr, "*")
    dr.AcceptChange s()
    .Rows.Add(dr)

    Me.ProgressBar1 .PerformStep()

    ' With this, the grid is able to response to scrolling
    ' record using arrow key and mouse,
    ' but unable to resonse the column header click.
    Application.DoE vents()
    Next
    .EndLoadData()
    End With
    End If
    bFilling = False
    End Sub

    Private Sub btnStopFill_Cli ck(ByVal sender As System.Object, ByVal
    e As System.EventArg s) Handles btnStopFill.Cli ck
    QueryThread.Abo rt()
    End Sub



    Thanks
    JCVoon
Working...