4

I am using Visual C# sand I'm using a Windows Form rather than a console application. Therefore I'm not working in Main (), but rather in the Form File. I'm also very new to C# so sorry if some of my questions are stupid.

What I basically need to do is when my program starts up I need it to keep looping forever. Where would I put this code since I don't have a Main ()? Do I put it in the function that has InitializeComponent() in it? I need the loop to start right after the program starts. However, I have some variables that I need declared first before the loop. So basically I need the variables to be declared and then the infinite loop to start. The variables are global.

Secondly, I need the infinite loop to break when the user presses a button. How would I do this? I was thinking something among the lines of:

while (buttonIsPressed == false)
{
   //do whatever I need to do
}

However, I realized the button's function will never be called since I am stuck in that loop. I can't set the variable from the button's function if I never reach the button's function due to being in an infinite loop. Any ideas? I was thinking about threads but I have absolutely no experience with threads so am a bit reluctant to try it out.


Additional, from comments:

A chat application. When the program starts I need it to keep listening. However, when the user clicks "connect" it stops listening and instead initiates a connection

I am creating a chat client. So basically when my program starts up, I need it to keep listening. However, when the user clicks "connect" it needs to stop listening and instead initiate a connection

Community
  • 1
  • 1
fdh
  • 5,256
  • 13
  • 58
  • 101
  • 9
    Please read up a bit on how Windows Forms works. You are already looping forever. – John Saunders Dec 30 '11 at 22:57
  • I realize that, but I specifically need to loop a certain function. So when the program starts, I need a specific part to be looped forever. – fdh Dec 30 '11 at 22:58
  • 1
    What is it that your loop needs to do? You will have to look for an alternative. A Timer or a Thread are the more obvious choices. – H H Dec 30 '11 at 22:59
  • 3
    Don't loop yourself, there is already a loop built-in to Winforms. Application.Run(). while (buttonIsPressed == false) is a KeyUp event. Do read a tutorial or book, you'll get stuck very quickly when you don't understand event-based programming as required in Winforms. – Hans Passant Dec 30 '11 at 23:00
  • Looping forever will take up a whole thread, and really is not a great design choice. What is it you want to accomplish?# – Darren Young Dec 30 '11 at 23:01
  • Thanks. If a loop isn't the best option, could you maybe give a code example of an alternative? – fdh Dec 30 '11 at 23:03
  • @DarrenYoung A chat application. When the program starts I need it to keep listening. However, when the user clicks "connect" it stops listening and instead initiates a connection – fdh Dec 30 '11 at 23:04
  • there's a pretty good example of a chat app in the .net samples on MSDN. – Sam Axe Dec 30 '11 at 23:07
  • 1
    @Farhad, writing a chat application is probably not the easiest thing you can do to learn C#. Before doing this you will have to read and understand how sockets work. You ask about writing an infinite loop but I strongly invite you start learning the basic things first. – Darin Dimitrov Dec 30 '11 at 23:07
  • @Darin I am very familiar with sockets. I have created several network applications in C++ and C. However, in those applications, the client and server are two separate applications. However, this time I have merged them into one application which has me confused. – fdh Dec 30 '11 at 23:09

4 Answers4

12

That's a natural question for someone who's coming from a (completely) different background.

Programming Windows Forms applications is event driven. When a Windows Forms application starts, a form is loaded (check Program.cs file) and there is a Main loop that is hidden from you to concentrate on the important things in your program.

You don't need to put anything in the Main loop to respond to an event (like a button clicked event). You just handle the button clicked event by creating an event handler for the Click event of the Button). You can use the designer or do that manually in the code.

When you create a method to handle an event (and as such the method is called an event handler) it is called automatically when the event is raised/triggered. For example a method handler for the Click event for the Button on your form would be called when the user clicked the button.

This MSDN topic contains all the information you need: Creating Event Handlers in Windows Forms. If you need more clarification, please ask! :)

UPDATE: Create an event handler just like above and also create a loop in the Form_Loaded event handler. Be sure to call Application.DoEvents(); inside the loop. This way the event handler for the button click can be handled (in the handler add code to modify a boolean that would make the loop's condition false to cancel the loop).

UPDATE 2: To make this answer more complete, I mention that you should also consider running the loop on a new thread, not the UI one (and therefore avoid needing to use DoEvents, which has its negatives as my peers pointed out). The following example shows how to create a Thread and cancel it on a Button Click:

    System.Threading.Thread t;
    private void Form1_Load(object sender, EventArgs e)
    {
        //create and start a new thread in the load event.
        //passing it a method to be run on the new thread.
        t = new System.Threading.Thread(DoThisAllTheTime);
        t.Start();
    }

    public void DoThisAllTheTime()
    {
        while (true)
        {
            //you need to use Invoke because the new thread can't access the UI elements directly
            MethodInvoker mi = delegate() { this.Text = DateTime.Now.ToString(); };
            this.Invoke(mi);
        }
    }

    private void button1_Click(object sender, EventArgs e)
    {
        //stop the thread.
        t.Suspend();
    } 

Finally, consider using a BackgroundWorker which encapsulates creating and managing Threads for you.

Lzh
  • 3,585
  • 1
  • 22
  • 36
  • Thanks! That explained a lot. Just one last question: you said everything is event driven. If that is the case, where would I put code that I want to run without an event. For example, you said button handler's are called when button's are pressed etc. But what if I want to run code that runs when the program starts up rather than when a event is called? Where would I put this kind of code? Thanks again. – fdh Dec 30 '11 at 23:35
  • 3
    Suggesting DoEvents to force the the button click to go off is not a good idea, for reaons explained here: http://stackoverflow.com/a/5183623/466903 A BackgroundWorker is a much better idea. – diggingforfire Dec 30 '11 at 23:40
  • @Farhad, depending on what the code is meant to do, I'd put it in the Load event of the Main form, in the Static constructor of the main form's class (which is run when the form's class is used and that's as soon as the program runs), or in the Main function in the Program.cs file. – Lzh Dec 30 '11 at 23:51
  • @diggingforfire, DoEvents is simpler for a beginner. I suggested the loop to be in Form_Load. The loop therefore is launched once, and the user doesn't have the ability to launch it again (so there is no 3 feet problem). The Form_Closed event should be handled to End the application and not leave the loop running. Thanks for bringing it up! – Lzh Dec 31 '11 at 00:03
  • I'm sure it's simpler for a beginner and it might not be a problem here, but it could cause someone to pickup a bad habit. I don't think the former outweighs the latter. – diggingforfire Dec 31 '11 at 00:05
  • In my previous comment, I posted ways to address the negatives of using DoEvents. It's not completely evil to use it. But I understand your concerns. I will modify my answer to include alternatives. – Lzh Dec 31 '11 at 00:23
  • There is absolutely nothing "simple" about `DoEvents`. The only people who should use it are the people who understand the Windows messaging model, and beginners (especially the person asking this question) emphatically *do not*. Good thing you added the update to avoid my -1. – Cody Gray - on strike Dec 31 '11 at 10:00
1

Why do you need it to keep looping forever?

The interesting thing to point out here, is that your program does this anyway; it's called the message loop. It is continuously receiving messages, as the user interacts with it (clicks buttons etc.)

What are you actually trying to do? There is certainly already a construct that will do what you are looking for, be it a Timer, BackgroundWorker, etc.

To listen on a TCP socket, there is the TcpListener class. You could fire up a thread for the TCP listener to run in.

Jonathon Reinhart
  • 132,704
  • 33
  • 254
  • 328
  • I am creating a chat client. So basically when my program starts up, I need it to keep listening. However, when the user clicks "connect" it needs to stop listening and instead initiate a connection. – fdh Dec 30 '11 at 22:59
  • @Farhad: Ouch. You need blocking I/O, not a loop. – H H Dec 30 '11 at 23:07
  • Thanks but I'm using UDP Sockets not TCP sockets. – fdh Dec 30 '11 at 23:17
  • +1 for mentioning Timer. You can use this to periodically do something (every 1 ms or 1 minute). – Lzh Dec 30 '11 at 23:27
1

If you need your form to respond to a button click, the loop will have to take place in a thread other than the main thread, a BackgroundWorker would suit you.

diggingforfire
  • 3,359
  • 1
  • 23
  • 33
  • I have absolutely no idea how to do that. Could you give a simple example please? – fdh Dec 30 '11 at 23:01
  • 2
    Before doing that, please take the other comments to heart and get to know how events work. A working example can be found in the MSDN link to the BackgroundWorker. – diggingforfire Dec 30 '11 at 23:03
  • Already dozens of examples on SO. And then there is [MSDN](http://msdn.microsoft.com/en-us/library/cc221403%28v=vs.95%29.aspx) – H H Dec 30 '11 at 23:06
0

It seems that you are trying to create a chat client (see this example for some sample code). For long running parallel executions I recommend that you create and start a thread whose body is the while loop you mentioned.

The key thing you have to understand is that there will be two threads of execution. One is the UI Thread who is responsible for drawing the form and reacting to events such as button clicks (note: this will loop forever reacting to events as the user interacts with the UI). The other thread is the looping background thread which you will create to listen for network information. The sample chat client referenced above creates the thread in response to certain button being clicked, but since you want to start looping as soon as possible I recommend that you create and start the thread in response to the Load event (just double click on the form in designer mode in Visual Studio to create the appropriate load event handler).

The tricky part is when you want to update a UI element from the background thread. To do this without exceptions you have to marshal the method call to the UI thread. This can be accomplished using the invoke method on any control (again see the referenced sample code).

To break out of the loop you can set a buttonPressed flag to false in a button clicked event handler. This eventhandler will be run on the UI thread but the shared flag will let the background thread break out of its loop the next time it iterates to the condition statement.

Darwyn
  • 4,696
  • 3
  • 25
  • 26