2

I am having a problem getting the main Form in my program to run as I want. I am using C#. On my initial main form (Form1) I have a command button that runs a long program. In the middle of the program I want the user to be able go back to the initial form and click on some new checkboxes that I will place on that initial form from within the C# program. The code below just freezes the initial form. I do not need to get the code below to work exactly. I just need it to allow me to access the main initial form in the middle of the program that I started with the command button.

To do this I have an infinite while loop that calls the timer. Is this the correct way to do this? I do not need the program below to work. I just need to be able to access that initial Form in the middle of the program. Since it is not working it seems that it is not the way to do this but what is the correct way?

The following code runs the OnTimedEvent function (method) below. The function used to put up a Messagebox but I commented that out. I do NOT need that function to work. It is only there for testing purposes. My goal is that I need the initial main Form to allow me to enter more information while it is running from the command button. The function below runs about 15 times and I get the error

Exception of type 'System.OutOfMemoryException' was thrown.

on the line aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);

The code is below:

System.Timers.Timer aTimer;
// Create a timer with a one second interval.
aTimer = new System.Timers.Timer(100);

while (true)
{
    // Hook up the event handler for the Elapsed event.
    aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);

    // Only raise the event the first time Interval elapses.
    aTimer.AutoReset = false;
    aTimer.Enabled = true;  // uncommented this now
    //addded  below
    aTimer.Start();
}

I have tried it in several different ways but the main Form always just freezes. I just want to be able to select things (checkboxes, for instance) on the main Form (Form1) so the below code may not be needed. The timer above calls OnTimedEvent which is below.

private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
  // MessageBox.Show("Hello World");
}

In many places on the web I have seen (including stackoverflow) that I should be using timers to get the main initial Form to be useable but the code above just causes the Form to be Frozen and I get the bar at the top of the form indicating that it is Not Responding. I am using Windows XP and Visual Studio 2008. As I indicated above I am using C#.

To summarize, is the above code the correct way to get the main, Initial form to be available after a command button has been running? If it is, what am I doing wrong? If this is not the correct way, what is?

BTW, I asked a completely unrelated question about this project here

Any ideas?

Community
  • 1
  • 1
Jim
  • 1,056
  • 1
  • 13
  • 19

4 Answers4

3

You should simply remove the while loop

    System.Timers.Timer aTimer;
    // Create a timer with a one second interval.
    aTimer = new System.Timers.Timer(1000);
    // Hook up the event handler for the Elapsed event.
    aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);

    // Only raise the event the first time Interval elapses.
    aTimer.AutoReset = false;
    aTimer.Enabled = true;  // uncommented this now
    //addded  below
    aTimer.Start();

Timer runs on a separate Thread when you start it. Your while loop just keeps starting the timer over and over again.

System.Timers.Timer

Ruben-J
  • 2,663
  • 15
  • 33
  • haha, I know, but i just copied it from the initial post. I'll change it FYI ;) – Ruben-J Apr 24 '13 at 19:02
  • @Ruben-J I tried using your code and it did not work. I increased the time to 60 seconds (60000). I ran it in the debugger. Would that make a difference? – Jim Apr 24 '13 at 19:25
  • We need more context. If this part is placed in the main method it won't block the UI thread. – Ruben-J Apr 24 '13 at 20:41
  • @RubenJ After I created the command button, I put all the code in the function `private void RunItButton_Click(object sender, EventArgs e)` – Jim Apr 24 '13 at 21:29
2

To do this I have an infinite while loop that calls the timer. Is this the correct way to do this?

No. The while loop blocks the UI thread, which in turn makes the program freeze. There's no reason to have the while loop as you're already using a timer to trigger the event.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • As I indicated to RubenJ: I tried using your code and it did not work. I increased the time to 60 seconds (60000). I ran it in the debugger. Would that make a difference? – Jim Apr 24 '13 at 19:27
1

Without seeing your full, actual, code it's hard to say, but the tradtional method of doing a long-running process without locking the UI is to use Threading in C#.

Can you do your long running action in its own thread so that you don't lock up the UI thread?

Here's a tutorial: http://msdn.microsoft.com/en-us/library/aa645740(v=vs.71).aspx

Laurence Moroney
  • 1,263
  • 8
  • 20
  • 1
    If I had all of my code in a thread, how would the thread talk to UI and vice-versa? Thanks for the suggestion... – Jim Apr 24 '13 at 20:36
  • Using the BeginInvoke on the Dispatcher, like here: http://msdn.microsoft.com/en-us/library/cc190259(v=vs.95).aspx – Laurence Moroney Apr 25 '13 at 05:08
1

Don't use a while loop. If you want to run your OnTimedEvent method once a second, use something more like this:

Timer myTimer = new Timer();
myTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
myTimer.Interval = 1000; // 1000 ms is one second
myTimer.Enabled = true;
myTimer.Start();
tnw
  • 13,521
  • 15
  • 70
  • 111
  • I changed your section of code to the following but it just ran through without stopping. I changed the time to 60000 which is 60 seconds... I allso added Systems.Timers to the 2 places in the first line ` System.Timers.Timer myTimer = new System.Timers.Timer(); myTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent); myTimer.Interval = 60000; // 1000 ms is one second myTimer.Enabled = true; myTimer.Start();` – Jim Apr 24 '13 at 19:41
  • @Jim You have to hold the program somehow. What platform are you in? WPF? Winforms? Console app maybe? – tnw Apr 24 '13 at 19:50
  • What do you mean by hold the program? I have a full featured Windows app so it is not a console app. How can I tell? – Jim Apr 24 '13 at 19:53
  • @Jim I guess I'm not really sure what you mean by "it just ran through without stopping". Did it work at all? Did your message box pop up? – tnw Apr 24 '13 at 19:59
  • I have a messagebox come up after that section of code is run and just goes onto the messagebox without doing anything.... Perhaps I am thinking of this wrong. I expect that my initial form window would be available and clickable for 60 seconds. Is that right? – Jim Apr 24 '13 at 20:13
  • @Jim Your first sentence makes absolutely no sense. – tnw Apr 24 '13 at 20:45
  • `MessageBox.Show(msg);` Right after your code is run, the next xtatement is `MessageBox.Show(msg);` and it is run without waiting 60 seconds. – Jim Apr 24 '13 at 21:09
  • So you're saying you have a *second* `MessageBox.Show(msg);` right after my code? – tnw Apr 24 '13 at 21:15
  • That's right. And it is just running straight through your code and going onto the `MessageBox.Show(msg);`. Am I correct in thinking that the problem is not that it is being run in the compiler? Also, when that code is run, what should happen? – Jim Apr 24 '13 at 21:24
  • That's because the call to your method that runs when the timer ticks 60s runs on a separate thread. Execution of code after `myTimer.Start()` will happen immediately. Take away the second `MessageBox.Show` and just let the program run. Every 60 seconds, that timer event will fire, and you should see your `MessageBox` pop up. – tnw Apr 25 '13 at 00:08
  • the funny thing is that that was what I had originally but I did not think it would help me so I put in the while loop. :-) How does this help though? Can I change the initial form from within the now uncommented `MessageBox.Show("Hello World");` in `OnTimedEvent` while the rest of the program is running? – Jim Apr 25 '13 at 13:37
  • Is there any way to get the main program to stop running while someone selects my newly created items on the main initial form? – Jim Apr 25 '13 at 13:50
  • Yeah, probably. Your questions are becoming way to localized... it's extremely difficult to answer your questions with this little context. I can't really help you any further. – tnw Apr 25 '13 at 13:59
  • No problem. Good luck, Jim. – tnw Apr 25 '13 at 15:06