views:

978

answers:

4

My C# application is running at system startup, and must wait for the local SQL Server instance until it can actually do anything. Right now, I just spin waiting for the server to respond (I used to get a wait handle on the service, but that wasn't reliable), then launch the app's main dialog.

The problem with this, of course, is that the user can't tell anything is happening until the service starts, and because of the hardware we're using that can take up to a minute. So I'm thinking of throwing in a "Loading / Please Wait" indicator of some sort. The thing is, our project is nearing lockdown and a change as big as making a new class would cause a lot of headaches -- modifying an existing file (like Program.cs) is a lot less intrusive than making a new one. Long story short: is there a .NET class that would be well suited to being displayed (asynchronously, I guess) before I start plinking at the SQL Server, then removed when it starts to respond?

+2  A: 

Here's a .NET wrapper around the standard Windows progress dialog:

http://www.codeproject.com/KB/shell/iprogressdialognet.aspx

I haven't messed with it, but I'm sure there's a Flag to make the progress bar spin. If you want to get really fancy, you could even whip up your own AVI animation and plug it in.

David Brown
This sounds great, except that it would be adding a new file, which was what I was trying to avoid in the first place. The reason I said "stock" is I'd like something you can get by installing a retail VS 2005 disc on a retail Win XP machine.
Coderer
Well in that case, there's not really anything you can do. There's no stock dialog, so adding a new file is inevitable for this sort of thing.
David Brown
+1  A: 

As easy as a "Please wait..." dialog is to build, I can't see why.

To my knowledge, no. There isn't a stock one. It's almost easier to grow your own... or just disable the form, and bring up the hourglass cursor. Same idea, and just as easy to implement.

Jerry
Again, I'm just trying to avoid creating a new class file for project-management reasons. If I can add one or two lines of code, I'll do it. If I have to add 50 lines of code in a new file, I won't.
Coderer
If 50 lines of code is going to ruin your project management scheme, it's probably a sign that you need a new one.
David Brown
A: 

You might consider doing your SQL work within BackgroundWorker (in a worker thread). That would leave your application responsive.

Miha Markic
The problem is that our initial dialog uses some SQL databindings, and there's not an easy way to say "turn these off until the 'Server Responding' flag is set by this other thread". At least, I don't *think* there is.
Coderer
+2  A: 

Here's a triple threaded version that I hacked together quickly that will do the trick. This can be dropped in anywhere in a visible form (or could be modified for program.cs) and will spawn a new, centered, modal dialog box with a smooth scrolling progress bar that will dominate user attention until FinishedProcessing in the parent thread is set to true.

        //Update to true when finished loading or processing
        bool FinishedProcessing = false;  

        System.Threading.AutoResetEvent DialogLoadedFlag
            = new System.Threading.AutoResetEvent(false);  


        (new System.Threading.Thread(()=> {

            Form StockWaitForm = new Form()
            { Name = "StockWaitForm", Text = "Please Wait...", ControlBox = false,
                FormBorderStyle = FormBorderStyle.FixedDialog, StartPosition = FormStartPosition.CenterParent,
                Width = 240, Height = 80, Enabled = true };

            ProgressBar ScrollingBar = new ProgressBar() 
            { Style = ProgressBarStyle.Marquee, Parent = StockWaitForm,
            Dock = DockStyle.Fill, Enabled = true };  

            StockWaitForm.Load += new EventHandler((x, y) =>
            {
                DialogLoadedFlag.Set();
                (new System.Threading.Thread(()=> {
                    while (FinishedProcessing == false) Application.DoEvents();
                    StockWaitForm.Invoke((MethodInvoker)(()=> StockWaitForm.Close()));
                })).Start();

            });  

            this.Invoke((MethodInvoker)(()=>StockWaitForm.ShowDialog(this)));  


        })).Start();  

        while (DialogLoadedFlag.WaitOne(100,true) == false)  Application.DoEvents();     
        //
        //Example Usage
        //Faux Work - Have your local SQL server instance load here
        for (int x = 0; x < 1000000; x++) int y = x + 2;  

        FinishedProcessing = true;

Customize to taste. Also, if you do use this in a production app, wrap the new thread contents in try...catch blocks to CYA. One last thing, I'm releasing this code to you under the "Coderer Public License / SO v1.1", as follows:

Coderer Public License / SO v1.0
I, Person known "Coderer" on the community "Stack Overflow", agree to thoroughly consider switching to a sane project management methodology that allows extra classes to be added to projects in the Executing phase. I understand that nazi-like change control is unhealthy for all parties involved.

Robert Venables
Funny thing, I did almost exactly this last night on my own. I don't think you need 3 threads -- I only used two. As for project management, the thing is that we don't have an Executing phase, we have a Out Of Our Control Forever And Ever phase. And we're *almost* there.
Coderer