Add a spinning wheel while application is searching database - vb.net

I have an application that searches in a database for some information.
Since the database is quite big, it sometimes takes a lot of time before the application returns the results to the interface.
I want to add some sort of spinning wheel to inform the user that the application is still searching the database and did not freeze. Once the results are returned, the wheel should disappear.
Any idea how to do this or is there a good tutorial explaining how to do this?

Have you considered changing the mouse pointer to the hourglass as this would be extremely simple to implement:
Me.Cursor = Cursors.WaitCursor
...Do your DB calls here...
Me.Cursor = Cursors.Default
However, I would agree that display a 'spinning wheel' is probably a little more user friendly and definately a lot more obvious. So, first get hold of an animated gif that suits your needs. Then create a form that has a picture box containing the image.
Once you have that you can show the form to the user and in the background do the DB work, once this has completed close the form.
Another alternative would be to use a rolling progress bar instead, so when it reaches 100% it cycles around again and keeps going until you close it.
EDIT:
One thing that I forgot to mention is that you will have to handle exception conditions. Lets say you set the cursor to wait, then an error occurs. The exception may bypass the code that resets everything. This leaves the user with a changed cursor and no means of changing it.
When I have done this kind of thing I have typically created a disposable WaitCursor class and then used something like this:
Using myWaitCursor As WaitCursor = New WaitCursor
...do something...
End Using
In the Dispose of the WaitCursor class you set the cursor back to default. The same would apply if you went down the route of using a form with an image or progress bar.

Find an animated gif of such a spinner, like this one. Put it in a PictureBox, set its Visible property to True when you start the job. Beware that you'll have to run the query in a worker thread to keep the animation alive and the user interface responsive. The BackgroundWorker class is good for that.

You could use the Environments Default wait cursor, which for Vista/7 is a circle with the outside spinning, or the XP tumbling hourglass.
You could launch your DB access on a BackgroundWorker and show an animated control such as a Marquee progress bar, or you could show a custom animation to show Busy status.

Related

Stuck in infinite loop. Any way to break vba into Code when Control+Break doesn't work

I have code stuck.
It might be in an infinite loop.
Not sure.
Is there a way to break the program to stop at the current line of code that it is running on?
I'd like to avoid shutting down excel because I want to be able to catch where in the loop it is, and by going into the code, I will be able to tell how much processing was done. I would like to break into the code, if possible.
It is stuck on hour glass.
Ctrl+Break doesn't seem to work
Seems like the running code has hijacked all the quota that cpu is giving to excel.
If there is nothing I can do now, is there something in the future I can do to where I can more easily break into the code?
I'm thinking that an intermittent wait within a loop might be a feasible solution.
In the future, include a DoEvents inside the loop. It will run a little slower, but you will be able to use Ctrl+Break to stop it from running.
Create a progress dialog when entering the loop and include a Cancel button. Within your loop check for the Cancel signal/event. This also gives you some flexibility on how you react to the Cancel - you could stop the loop and display key information in a new dialog box (for example).
Basic steps to achieve what I have described (not necessarily the most elegant or the most re-useable, but simple enough for those of lesser experience):
create a modeless (not modal) Form with either suitable labels or a progressbar item (for
visual effect). Include a public property (Boolean) for Cancel (e.g.
boolCancel)
Place a button on form and onClick set boolCancel = True
In your main code, show the form just before your problem loop.
while in your loop you can update some label or progress bar on the
form so that you have a visual indication of whether the loop is
doing something of value or if it is now simply spinning its wheels.
How you do this depends on what your loop is doing.
Also while in your loop check your boolCancel value. If true then
display any state information you want and break from the loop.
If your loop ends normally, hide/unload the progress dialog.

How to manage event for made a load bars in Access

I created an application with Access (2013) with VBA. This application crawls a website and inserts some records into database. But it takes too much time.
My solution is to make load bars for waiting. But currently I use the event Form_Current(); and when I set the load bar's value (it's my function) setBarLoadValue (25) Nothing is displayed on the screen. Why ? Because my function run yet.
My question is: How I can manage the event to simulate a load bar in real time ? (Don't want to wait till the end of function to see 100%).
The following link has a beautifully designed Progress status bar. http://www.access-programmers.co.uk/forums/showthread.php?t=265537
The author of the code has provided a Class where you have a Form that acts as a Meter and you basically set the values. It could be real time enough, have a look. I use it in my application and works great.
Finally I found an solution !
Solution
Step1
You must enter this code in your code
DoCmd.SelectObject acForm, Me.Name
Me.Repaint
DoEvents
With this code, you display immediately the form
Step 2
Now, when you want to display something, you must just do that: DoEvents.
When you use DoEvents the form refresh and you can display the new state of the progress bar.
Note: This solution work with Access 2013. Maybe it's not supported with other version.

Allowing two windows from the same APP to move

I'm making a VB.net application. I have a dialog that pops up at some points. It is set as TopMost. The problem is, when it pops up, you can't move the main form. How can I make it so it shows and is usable while allowing the main form to continue to be usable?
It sounds like you're calling ShowDialog(), but the behaviour you describe sounds like you want to call Show() instead (of course, this'll mean that you will not get the DialogResult, nor will the calling code block, but this allows the parent window message loop to handle things like moving the window)

Form not refreshing after ShowDialog (Compact Framework)

I'm having a weird issue with form painting in the Compact Framework. I have a login dialog that is basically a small form that is opened on top of another using ShowDialog. When a card is swiped, the login dialog is supposed to close, then some login tasks are performed and then the form behind it should be activated. The problem is that the form behind the login dialog is not being refreshed and so the login dialog will not be removed until after the form behind is refreshed by some user action. This is probably due to the heavy processing that goes on in the login tasks part, but I've not found a way to solve this.
Basically, I want a way to force the application to close the dialog and paint everything again, before performing the heavy login tasks. I've tried numerous refresh methods without any luck:
Form loginDialog = new Form();
DialogResult result = loginDialog.ShowDialog();
loginDialog.Dispose();
//I've tried everything at this point to get the form to refresh before performing
//login tasks
this.Refresh();
this.Invalidate();
Application.DoEvents();
PerformHeavyLoginTasks();
Does anyone know what could be going wrong? Thanks
Ok I figured this out. The problem was with a custom control on the background form that manually paints itself using rectangles and such. I think this is a compact framework bug since I called Refresh and Invalidate on that control as well and it should've repainted. I had to create a method that would call the control's OnPaint override directly since Invalidate and Refreshed were pretty much ignored.
The issue, I believe, is that you're not fully understanding what's going on system-wise here.
When your fore window (the Dialog) is dismissed, the background window (the Form) is given focu and tol to repaint the clipping region where the dialog was. This happens via a PostMessage call, which sends a Windows Message that has to be popped, translated and dispatched down in the bowels of the Application.Run call.
This is, by design, a fairly slow process as the UI should not be preempting things that are important.
If you are doing heavy processing immediately after that PostMessage happens, the processing of those windows messages can often be slowed, ending up with the UI appearing "locked" or drawing really slowly. This is exacerbated if the processing you're doing is on the same thread as the UI.
Why are your efforst not making things better?
Calling Refresh simply sends another message. That message now gets in line for processing, so it would actually make things worse.
Calling Invalidate does pretty much the same this as Refresh, just asynchronously. Again, it makes things worse.
DoEvents tells the message pump to pop, translate and dispatch a message. That dispatch still has to be processed on the UI thread, so noting is going to happen until the thread has time to do the work (i.e. after your processing)
So how do we "fix" this?
The first step is often to put the processing on a separate thread to allow the scheduler to round-robin tasks between the UI and processing threads, up to the default quantum. Thgis means that the processing can only starve the UI for a maximum of 100ms before some sort of drawing is allowed to occur (assuming equal thread priority).
new Thread(PerformHeavyLoginTasks)
{
IsBackground = true
}.Start();
You can go a step further and give the UI a "jump start" on the processing (of 10ms in this example):
new Thread(new ThreadStart(delegate
{
Thread.Sleep(10);
PerformHeavyLoginTasks();
}))
{
IsBackground = true
}.Start();
Of course this may mean you need to now handle the next "display" asynchrously if the UI you want to display is dependent on the processing result. There are plenty of online resources for async patterns, so I won't beat that dead horse here.

Datagridview retains waitcursor when updated from thread

I have a DataGridView control in my Windows Forms Application.
I am adding rows to the grid using a background thread. I change the form's cursor to Waitcursor when the process starts and back to Default when it ends. This works well for the form, but not for the grid. When the form's cursor is changed back to default, the grid's cursor does not change, although the cursor over the rest of the form does.
Does this have anything to do with the fact that I am updating the grid from a background thread? (The cursor is being changed from the UI thread directly).
Edit: The background process raises an event, the handler checks the InvokeRequired property of the grid and decides if it needs to "Invoke" the method again from the main thread. So, in effect the actual UI update happens from the appropriate thread. I am not sure if this means that I am "using a background thread" or not. :|
I've had some problems doing single thread updating of my datagrids, where the datagrid did not reset to normal cursor after i've had waitcursor to true.
What I did was right after i went
this.UseWaitCursor = false;
I added
DatagridviewFoo.Cursor = this.Cursor;
Maybe it's just the same problem for you
I've had this problem as well. It was difficult to track down the cause, let alone a solution.
This issue only ever happened when I had a dialog box over the DGV control and the mouse clicked on a button to close the box such that when the box closed, the mouse was over a (resizable) column border. If the cursor ended up over a cell, the problem didn't arise. If I had to guess, I'd say the grid was seeing a column resize event as soon as the dialog box closed which wasn't properly handled.
Using Cursor.Current = Cursors.Default fixed my issue (without the need to explicitly reset the control's cursor). But maybe be aware that Application.UseWaitCursor = False didn't work even with the explicit control cursor reset.
I had a similar problem, but neither of the posted solutions worked for me. Mine was not caused by clicking a button above a movable column separator. It just randomly happened after opening and closing a dialog box. I'm pretty sure it came down to timing because .Net/Windows has issues when it comes to setting cursors and actually having them take effect. To try to overcome that, the library we use for showing and hiding the wait cursor calls - ack! - Application.DoEvents. I set a breakpoint in OnCursorChanged and saw that the cursor was sometimes actually getting set on a latter call to Application.DoEvents (used to keep the UI responsive while waiting for the file system to release a write lock on a file). So I guess sometimes the default cursor was getting turned back on before the call to set the wait cursor had fully taken effect. Anyway, my brute-force approach is to call
Cursor = Cursors.Default;
in my override of OnCellEnter (which always happens after the grid gets refreshed following the dialog box being closed). I'm not particularly proud of this, but it seems to work.