Click here to Skip to main content
15,892,575 members
Please Sign up or sign in to vote.
2.50/5 (2 votes)
See more:
Hi all

Wanted to know if anyone had sorted this at all:

I want to do something on a backround worker thread that updates the Form whilst the Form is busy doing something. When I say busy, it might be performing some queries on a database that could take a while.

As queries on the database essentially make the program hang, the background worker thread doesn't update the screen whilst the query is going on and I can't issue the queries on their own thread, as we're using an alpha DB, and the connection isn't thread safe.

Have tried a simple program with a background worker thread that is kicked off on clicking a button. Updates to the screen happen in the thread. Immediately after the thread is kicked off (.RunWorkerAsync) I simulate something happening like a query being issued by using a sleep for 10 seconds (Sleep(10000)).

The screen is not updated whilst the sleep is active, even if I use Application.DoEvents(). It does update without a sleep

I'm pretty sure what I'm askng is not possible, but you never know.

Thanks for reading!

Julian
Posted

First, there's no reason a form should be "busy". Your query should be in its own thread, and should notify the form when it's done via an event. At that point, your form is free to handle other events from other threads, such as a BackgroundWorker. Finally, why on earth do you have a Sleep method on the form's thread?
 
Share this answer
 
v2
Comments
julian@giant 27-Jun-11 8:45am    
That would be nice if the query was issued in a thread. However, the query is issued on the main thread and code execution stops until the query is finished. And as stated, I can't issue the query on it's own thread.

Am I missing something?
Kim Togo 27-Jun-11 8:51am    
Why can you not run the query on a worker thread?
#realJSOP 27-Jun-11 14:45pm    
Unless it's a code restriction, you *can* run this from a thread. just create the SQLConnection object as a public member in astatic class, and instantiate it. OInce that's done, a separate/background thread can access it, and when it's done, the connection remains open (uness, of course, the thread closes it). Just because the connection isn't thread-safe doewsn't mean your code can't be. It just requires a bit more caution on your part, that's all.
julian@giant 27-Jun-11 8:55am    
The connection to the database remains open for the life of the application. The connection is created on program startup on the main thread. Issuing a query on a separate thread hasn't worked properly in the past, I don't think the interface to the DB is up to it. It's an alpha database running on VMS. We connect to it at the moment from a .Net application using ADODB.
julian@giant 27-Jun-11 9:18am    
I don't think what I'm trying to do is possible. Thanks for your comments anyway.
Julian
There is another way for a non-UI thread to communicate to UI, much more general one.

You cannot call anything related to UI from non-UI thread. Instead, you need to use the method Invoke or BeginInvoke of System.Windows.Threading.Dispatcher (for both Forms or WPF) or System.Windows.Forms.Control (Forms only).

You will find detailed explanation of how it works and code samples in my past answers:
Control.Invoke() vs. Control.BeginInvoke()[^],
Problem with Treeview Scanner And MD5[^].

See also more references on threading:
How to get a keydown event to operate on a different thread in vb.net[^],
Control events not firing after enable disable + multithreading[^].

—SA
 
Share this answer
 
The only way a background worker can communicate back to the form, as far as I know, is through the ReportProgress method which triggers the ProgressChanged event. But depending upon what kind of updates you are trying to make on the screen...this might be enough. For example, if all you are trying to do is change a label so it will report to the user that the process is now on Step 2, you can just setup the ProgressChanged event to do it. Here's a sample of how I've used values 0-9 when reporting progress to update labels and the progressbar on my form...and then any value greater than 9 sets the progressbar value.

VB
Private Sub bgwSync_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles bgwSync.ProgressChanged
    Select Case e.ProgressPercentage
        Case 0
            'Error
            barProgress.Value = 0
        Case 1
            lblMessage.Text = "Checking for program updates..."
            barProgress.Value = 5
        Case 2
            'performing program update
            lblMessage.Text = "Updating program..."
            barProgress.Value = 15
        Case 3
            lblMessage.Text = "Processing Step One..."
        Case 4
            lblMessage.Text = "Processing Step Two..."
        Case 5
            lblMessage.Text = "Retrieving data..."
        Case 6
            lblMessage.Text = "Downloading files..."
            barProgress.Value = 15
        Case 7
            lblMessage.Text = "Loading tables..."
        Case 8
            lblMessage.Text = "Processing Step Three..."
        Case 9
            lblMessage.Text = "Processing Step Four..."
        Case Is >= 10
            barProgress.Value = e.ProgressPercentage
    End Select
End Sub


If you are trying to be more specific and want to report a string value like a filename or something and where it is being used in the process...you still might be able to use the idea above but you would have to get the filename or whatever the same way on the form as you do in the backgroundworker and use an integer value from 0 to 100 to reference it on both sides. So it's limiting, but might be possible.

Hope this helps.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900