PHP User Warning: fetch_template() calls should be replaced by the vB_Template class. Template name: bbcode_highlight in ..../includes/functions.php on line 4197

PHP User Warning: fetch_template() calls should be replaced by the vB_Template class. Template name: bbcode_highlight in ..../includes/functions.php on line 4197
VS 2012 [RESOLVED] Form takes time to load, implement BackgroundWorker?-VBForums
Results 1 to 9 of 9

Thread: [RESOLVED] Form takes time to load, implement BackgroundWorker?

  1. #1

    Thread Starter
    Hyperactive Member
    Join Date
    Feb 2009

    Resolved [RESOLVED] Form takes time to load, implement BackgroundWorker?


    I have form that loads data from a remote server. In the Form_load event I have close to 15 queries that populate various combo boxes and Data Grid Views. It usually takes up to 30 seconds to display a form. All that time, the UI is unresponsive.

    Here's how a typical query looks like: Code:
    1. Dim connection as New SqlConnection(connectionString)
    2. Try
    3.              connection.Open()
    5.             Dim sqlQuery As String = "SELECT scheduleStatusID,scheduleStatusName FROM scheduleStatuses"
    6.             Dim myCommand As New SqlCommand(sqlQuery, connection)
    8.             Dim scheduleStatusTable As New DataTable
    9.             Dim scheduleStatusAdapter As New SqlDataAdapter
    11.             scheduleStatusAdapter.SelectCommand = myCommand
    12.             scheduleStatusAdapter.Fill(scheduleStatusTable)
    14.             scheduleStatusAdapter.Dispose()
    15.             myCommand.Dispose()
    17.             If scheduleStatusTable.Rows.Count > 0 Then
    18.                 cmbScheduleStatuses.DataSource = scheduleStatusTable
    19.                 cmbScheduleStatuses.DisplayMember = "scheduleStatusName"
    20.                 cmbScheduleStatuses.ValueMember = "scheduleStatusID"
    21.                 cmbScheduleStatuses.AutoCompleteMode = AutoCompleteMode.Suggest
    22.             Else
    23.                 cmbScheduleStatuses.DataSource = Nothing
    25.             End If
    29.         Catch ex As Exception
    30.               MessageBox.Show ("Test error")
    31.               connection.Close()
    32.         Finally
    33.               connection.Close()
    34.         End Try

    Having the UI unresponsive just looks bad, so I wanted to move all the queries to a separate thread. And while the data is being loaded, maybe display a Loading message.

    Using the BackgroundWorker component I can place all the queries in the DoWork event. BUT,I cannot access the controls that are in the UI thread. So I can't set the DataSources of the controls being populated.

    So my main question is how do I do this? How do I load the data for one Combo Box, set the Data Source and move to the next control?

    Thank you!

  2. #2
    I don't do your homework! opus's Avatar
    Join Date
    Jun 2000
    Good Old Europe

    Re: Form takes time to load, implement BackgroundWorker?

    The BackGroundworker has two major Event-Routines, they are DoWork and RunWorkerCompleted. The first is called (started) by .RunWorkerAsync(), which will start the BackgroundWorker in its thread. The RunWorkerCompleted is raised when the DoWork is completed is is done on the GUI-Thread, in other words in this routine you can access the GUI.
    You're welcome to rate this post!
    If your problem is solved, please use the Mark thread as resolved button

    Wait, I'm too old to hurry!

  3. #3

    Thread Starter
    Hyperactive Member
    Join Date
    Feb 2009

    Re: Form takes time to load, implement BackgroundWorker?

    I understand that. In my form load I call .RunWorkerAsync, which starts the BackgroundWorker. But if I place the above query in the DoWork event, it will not be good, because I have cmbScheduleStatuses.DataSource in it. And cmbScheduleStatuses is in the UI thread. So how do I remove all the parts of the above query that deal with UI controls to the RunWorkerCompleted?

  4. #4
    Frenzied Member IanRyder's Avatar
    Join Date
    Jan 2013
    Healing, UK

    Re: Form takes time to load, implement BackgroundWorker?


    All you need to do is make sure that you pass the right information between the events. Here is an example flow of what you could do. You add all the results to a dataset and then pass the resulting dataset back to the UI thread when its built. The process of then binding that information to the controls is then almost instantaneous. Code:
    1. Public Class Form1
    2.   Private controlDS As DataSet
    4.   Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    5.     Me.Cursor = Cursors.WaitCursor
    7.     With BackgroundWorker1
    8.       .WorkerReportsProgress = True
    9.       .RunWorkerAsync()
    10.     End With
    11.   End Sub
    13.   Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
    14.     Dim tempDS As New DataSet
    16.     'Add the Tables you need to a Dataset
    17.     With tempDS.Tables
    18.       .Add("comboProducts")
    19.       .Add("comboPrices")
    20.     End With
    22.     'Populate each Table with your SQL Fill Statements
    24.     'After each table is filled report some progress to the UI Thread if you want to
    25.     BackgroundWorker1.ReportProgress(1, "Products Table")
    26.     'Continue for each table to be loaded
    28.     'Finally pass the Dataset back to the UI Thread and populate the Controls that you need
    29.     e.Result = tempDS
    30.   End Sub
    32.   Private Sub BackgroundWorker1_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
    33.     MsgBox(String.Format("{0} percent completed and {1} has been Loaded", e.ProgressPercentage, e.UserState.ToString))
    34.   End Sub
    36.   Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
    37.     controlDS = DirectCast(e.Result, DataSet)
    39.     With ComboBox1
    40.       .DisplayMember = "SomeFieldName"
    41.       .ValueMember = "SomeFieldName"
    42.       .DataSource = controlDS.Tables("comboProducts")
    43.     End With
    45.     'Add to the rest of the controls as you need to
    47.     Me.Cursor = Cursors.Default
    48.   End Sub
    49. End Class

    You should be able to build what you actually need from here.

    Hope that helps.



  5. #5

    Thread Starter
    Hyperactive Member
    Join Date
    Feb 2009

    Re: Form takes time to load, implement BackgroundWorker?

    Hello Ian,

    Thank you for your explanation. That looks like exactly what I need. Will try it out when I get to office tomorrow

  6. #6
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002

    Re: Form takes time to load, implement BackgroundWorker?

    I would agree with that. I have a similar problem in a working app. In my case, the form that will show the data is not the startup form, nor is it even a form that the user will get to in the first several seconds, but once they try to open that form, it can take more than 10 seconds to populate the controls. The solution I used was to start a thread as soon as the app started. The thread would populate a dataset in the background while the user was doing other things. If they did manage to reach the key form before the thread had finished filling the dataset, they would see a temporary message asking them to wait, but I've only seen that message one time, since it's hard to get to that form very quickly.

    In any case, once the datasets have been populated, binding them to the controls takes no noticeable time at all. The price is paid in all the database activity, the binding is nearly free. Therefore, the solution is to fill the datatables in the background, then bind in the foreground.

    One thing you might also consider is whether or not you can start filling those tables even earlier. Technically, you could start the BGW or a thread or Task, in the constructor, but unless you are doing other things in the constructor, it won't help at all to move from the Load event to the constructor. Also, if the form is not the startup form, can you load all, or even some, of the datatables prior to showing the form?
    My usual boring signature: Nothing

  7. #7
    Bad man! ident's Avatar
    Join Date
    Mar 2009

    Re: Form takes time to load, implement BackgroundWorker?

    Off head comment: Surely if getting data from a server the SqlConnection etc has some sort of async, or callback method?

  8. #8

  9. #9

    Thread Starter
    Hyperactive Member
    Join Date
    Feb 2009

    Re: Form takes time to load, implement BackgroundWorker?

    Well, I used Ians suggestion and it really worked nicely. There was quite a lot of work because I needed to separate the UI elements from the actual code the only loads the data. I even managed to use ReportProgress to update a label on a semi-transparent loading form, so it looks nice really.

    I did try moving all the code to the constructor, but that made no significant difference in loading time.

    I also looked at ident's example, but didn't use it, because honestly I didn't really understand the point

    To conclude, this is an example why planning your application is very important. While developing it, it never crossed my mind that there could be problems with all those queries. So now, I had to spend an entire day rewriting code only because I was "in a hurry"

    Thank you guys!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts


Click Here to Expand Forum to Full Width