views:

196

answers:

2

I am sorry if it seems like I am posting the same question. The problem is similar but I find out more and more about the problem each time. So thanks in advance for all the help. Its much appreciated. :D

I want to show a form/dialog given a certain condition while inside of a loop. My problem is I have created this segment of code in my program and when I meet my condition and Show my form it doesn't display properly. I have narrowed the problem down to the loop as it works fine else where in the program. But whenever I try to call the .Show method on my form before the loop starts or inside the loop it doesn't display properly. Specifically my form/dialog only has a single Label on it at the moment. Here is what happens when I call the .Show method on my form/dialog:

  • Unable to interact (IE move it around or close it with the 'X') with the form/dialog - The mouse icon shows that it is thinking/working if you hover of the form/dialog.
  • The background doesn't load - The border and title bar/header do load for the dialog but the background doesn't. In fact it isn't there to start so you can see through the form/dialog. If you click anywhere the background then goes to black.
  • The Label doesn't load - This probably is related to the background but you can't see the label or an outline/shading of where it ought to be.

Here is my segment of code:

    private void ConnectSequence(object sender, DoWorkEventArgs e)
    {
        EstablishingConnection ourECF = new EstablishingConnection();

        // Loop till connected
        while (!this.ourCC.Connected)
        {
            this.ourCC.InitializeConnection();

            // If we didn't connect and ourECF isn't already shown then show it
            if (!this.ourCC.Connected && false == ourECF.Visible)
            {
                ourECF.Show();
            }
        }

        ourECF.Dispose();
    }

Here is what I am trying to do:

  • Loop until a connection is made
  • If after the first attempt to connect is a failure display a form/dialog that alerts the user that attempts to establish a connection are being made

The code it self works great. If I turn the server off and run the client application it pops up the form/dialog that doesn't work properly. When I turn the server back on it gets out of the loop and disposes of the form/dialog. Currently I have a BackgroundWorker calling ConnectSequence as I thought this would solve my problem.

What I have tried so far:

  • Use of threads (System.Threads & BackgroundWorker)
  • Turning its .Visible property to true (.Show does this but gave it a whirl)
  • Instantiated ourECF and called it in as many different places as I could find to see if I could find a work around.

But in the end it doesn't work because of this loop. And I have no idea why. Any help would be much appreciated. I am so grateful for all your help. :D

+3  A: 

You're starving the message loop, forms require message pumping in order to display and function correctly, and your loop blocks this message pump from doing that, pumping and processing messages.

The "simplest" course of action is to intersperse your loop with Application.DoEvents(); calls, but that's a hack and often leads to bugs, like the user clicking on buttons twice to open two windows, etc.

The correct way is to handle this in a multithreaded manner, put the blocking code into a background thread... or ... place the form, which I understand is akin to a "Please wait, something is happening" type of form, in its own background thread by itself. Either of these solutions require some work to handle threading issues.

So first, check if DoEvents works for you, but make sure you try clicking in forms, closing the form, etc. to ensure you don't experience odd bugs later on.

Lasse V. Karlsen
+2  A: 

If you already used a BackgroundWorker, what didn't work with it??

        backgroundWorker.WorkerReportsProgress = true;

        backgroundWorker.DoWork += (newSender, newE) =>
        {
            while (!this.ourCC.Connected)
            {
                this.ourCC.InitializeConnection();

                if (!this.ourCC.Connected)
                {
                    backgroundWorker.ReportProgress(0, true);
                }
            }
        };

        backgroundWorker.ProgressChanged += (newSender, newE) =>
        {
            if (!ourECF.Visible)
            {
                ourECF.Show();
            }
        };

        backgroundWorker.RunWorkerCompleted += (newSender, newE) =>
        {
            ourECF.Dispose();
        };

        backgroundWorker.RunWorkerAsync();
Oliver