Windows Develop Bookmark and Share   
 index > Windows Forms General > How do you keep your application from freezing while it is trying to connect to a remote server?
 

How do you keep your application from freezing while it is trying to connect to a remote server?

Hello, any help here would be much appreciated.

In my program the client application connects to the server application over the internet. This works fine when I have the server application running. But if I turn the server application off (to simulate the server being down) the client application freezes while it waits for the server to time out. I am talking freezing. In windows Vista I get the (Not Responding) message in the title bar. But then once the server times out, my client application carries on just as I have programmed it to.

Also, I want to display a progress bar (in marquee style) while the client is waiting on the server.But for some reason, even though I call the code to run the progress bar before I call the code to connect to the server, the progress bar actually disappears from my form! However, it does return again once the server has timed out and control is returned to my program.

Here are the snippets of code involved in making this happen:

First the button event handler is called:
        private void btnLogin_Click(object sender, EventArgs e)
        {
            // Make sure username and password fields are not blank
            if (TestForEmptyLoginBoxes() == true) 
                return;

            // If existing user...
            if (cbNewUser.Checked == false)
                Login();
            else // If new user...
                CreateUser();
        }
Then that calls the Login() method. This method is longerbut I am only showing the code relevant to my question:
private void Login()
{
            string username = txtUserName.Text;
            string password = txtPassword.Text;
            bool connected = false;

            // Connect
            try
            {
                StartProgressBar("Connecting");
                connected = Connect(); 
            }
            catch (Exception e)
            {
                SetDisplay_lblError(e.Message);
                StopProgressBar();
            }
}
First Login() starts the progress bar(or is supposed to start the progres bar) by calling StartProgressBar():
        private void StartProgressBar(string progressLabel)
        {   
            progressBar.Style = ProgressBarStyle.Marquee;
            progressBar.MarqueeAnimationSpeed = 40;
            UpdateProgressBar(progressLabel); 
        }
StartProgressBar() then calls UpdateProgressBar which just changes the size of the progress bar and its corrosponding descriptive label.I know doing it that way is a little unusual but that's the way I chose to do it. Anyway, this is UpdateProgressBar():
 private void UpdateProgressBar(string progressLabel)
        {
            // Setup varibales
            Graphics g = this.CreateGraphics();
            Point pBarLoc = progressBar.Location;
            string newProgressString = progressLabel;
            SizeF oldLabel = g.MeasureString(lblProgress.Text, lblProgress.Font);
            SizeF newLabel = g.MeasureString(newProgressString, lblProgress.Font);
            int lblDif = (int)(newLabel.Width - oldLabel.Width);
            Rectangle changeRect = new Rectangle();

            // Chane the text box and progres bar
            lblProgress.Text = newProgressString;
            progressBar.Location = new Point(pBarLoc.X + lblDif, pBarLoc.Y);
            progressBar.Width -= lblDif;

            // Invalidate the controls so they are redrawn
            changeRect.Location = lblProgress.Location;
            changeRect.Height = progressBar.Height;
            changeRect.Width = (progressBar.Location.X + progressBar.Width) - lblProgress.Location.X;
            Invalidate(changeRect);
        }
After UpdateProgressBar() completes control is returned to StartProgressBar() which then completes and controls is returned to Login(). Login then calls Connect(). It should be noted that if I comment out the call to Connect(), everything works perfectly. But when comment runs the client application freezes for a while (which causes Vista to think my program has frozen) and then unfreezes once it's attempt to connect to the server times out. Here is the Connect() method:
        private bool Connect()
        {
            if (ChannelServices.GetChannel("chatAppChannel") == null)
                network = new Network();

            network.Connect();
            return true;
        }
Then Connnect() method creates a Network object. (I wrote the Network class myself, it's not from Microsoft). The Network constructor just registers the channel that will be used forremoting:
        public Network()
        {
            try
            {
                chatAppChannel = new TcpChannel();
                ChannelServices.RegisterChannel(chatAppChannel, false);
            }
            catch (Exception e)
            { throw new Exception("Remoting Error: unable to instantiate or register channel " + e.Message); }
        }
After the Network object has been created, network.Connect() is called:
public void Connect()
        {
            try
            {
                string serverAddress = Dns.GetHostEntry("www.myAddress.info").AddressList.ElementAt(0).ToString();
 
                serverObject = (ChatAppInterface.clientServerInterface)Activator.GetObject(typeof(ChatAppInterface.clientServerInterface), "tcp://" + serverAddress + ":1212/ServerObject");
              
                serverObject.ToString(); // test to see if the remote object is working
            }
            catch (Exception e)
            {
                string detail = e.Message;
                throw (new Exception("Error creating remote object. Details: " + detail));
            }
        }

As you can see, the way I am having my client find the server across the internet is to resolve a domain name into an ip address. That is not my actual domain name. It has been changed to www.myAddress.info for anonymity. Anyway this method does work when I have the server running and I am able to create and use the remot object. I believe it is here where the program ends up freezing while it tries creating the remote object on the server. Again, the reason it is unable to create the remote object is because I am not running the server application (for testing purposes). So it times out because of that but I imagine the client application would also freeze if the user had a very slow internet connection.

Anyway, after this method throws it's exception, control is returned to Login() which displaysan error message on the form. Then you can try to log in again and go through the same thing all over again. The program doesn't crash, it just freezes and for some reason turns the progress bar inivisible even though I don't specify anywhere for the progress bar to turn invisible.

So to sum up my question. How do I stop my appliction from freezing while it is trying to connect to a server on the internet? Also, why is my progress bar dissapearing??? If I use a thread somewhere will that help me?

Thanks for your help
WreckingBall2  Saturday, September 26, 2009 5:24 PM
Make new thread which connects to the remote host... before starting thread run the progressbar ...
OR make New Backgroundworker ....similar like this


Imports System.ComponentModel

Public Class Form1

    Dim Connecter As BackgroundWorker


    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Connecter = New BackgroundWorker
        AddHandler Connecter.DoWork, AddressOf Connect
        AddHandler Connecter.RunWorkerCompleted, AddressOf Connect_Complete
        ProgressBar1.Enabled = True
        ProgressBar1.Style = ProgressBarStyle.Marquee
        Connecter.RunWorkerAsync()
    End Sub


    Private Sub Connect()
        'code for connecting
    End Sub


    Private Sub Connect_Complete(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs)
        MsgBox("Connected")
        ProgressBar1.Enabled = False
        ProgressBar1.Style = ProgressBarStyle.Continuous
    End Sub

End Class


  • Marked As Answer byWreckingBall2 Saturday, September 26, 2009 6:41 PM
  •  
Lucifer L.  Saturday, September 26, 2009 5:39 PM
Make new thread which connects to the remote host... before starting thread run the progressbar ...
OR make New Backgroundworker ....similar like this


Imports System.ComponentModel

Public Class Form1

    Dim Connecter As BackgroundWorker


    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Connecter = New BackgroundWorker
        AddHandler Connecter.DoWork, AddressOf Connect
        AddHandler Connecter.RunWorkerCompleted, AddressOf Connect_Complete
        ProgressBar1.Enabled = True
        ProgressBar1.Style = ProgressBarStyle.Marquee
        Connecter.RunWorkerAsync()
    End Sub


    Private Sub Connect()
        'code for connecting
    End Sub


    Private Sub Connect_Complete(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs)
        MsgBox("Connected")
        ProgressBar1.Enabled = False
        ProgressBar1.Style = ProgressBarStyle.Continuous
    End Sub

End Class


  • Marked As Answer byWreckingBall2 Saturday, September 26, 2009 6:41 PM
  •  
Lucifer L.  Saturday, September 26, 2009 5:39 PM

You can use google to search for other answers

Custom Search

More Threads

• Serializing a Collection into a Settings file (default Settings.settings)
• FileSystemWatcher
• VB and Access Report
• Does VS2005 has Ouklook bar control in standard control collection?
• VB 2005 - TAB PROBLEMS
• Dynamically Resizing a Control
• how would I implement this editor
• Why Point class doesn't support -/+ by default?
• C# Form takes long time to close (Refresh!)
• Refresh problem with windows.Form