Click here to Skip to main content
15,896,453 members
Please Sign up or sign in to vote.
2.00/5 (3 votes)
See more:
How can I stop the main thread that is running on my application? I have three classes: the first class is in the main form, the second is a user control that has a button in it with an image, and the last thread is the class that contains a code that keeps on changing the icon of the button in the class usercontrol.

So as long as the main window is open, the thread just keeps on invoking the class usercontrol and the usercontrol class that contains the "main thread" calls the third Class.

The problem is when I close my main form, I notice that my main thread is still running. How can I close the main thread when I close my main form?

Sample code:
/* This is the Main form that is being displayed and it contains a flowlayout */

public Main(){

  InitializeComponent();
/* a flowlayoutpanel attached at the main form */
            flowLayoutPanel1.AutoScroll = true;
            flowLayoutPanel1.Dock = DockStyle.Fill;
            for (int i = 0; i < 10; i++)
            {
                //flowLayoutPanel1.Controls.Add(createButton((i+1) + ""));
                flowLayoutPanel1.Controls.Add(new Monitor());
            }


}
/*End of main form */





/* This is my 2nd class which is a usercontrol class */

public partial class Monitor : UserControl
    {
        check chk = new check();
        public static Thread thread;
        public Monitor()
        {
            InitializeComponent();
            thread = new Thread(chk.changecolor);
            chk.getButton = this.button1;
            thread.Start();            
     
        }
 
  
        private void button1_Click(object sender, EventArgs e)
        {
            chk.isChange = true;
        }
    }




/* This is the 3rd class that handles the changing of the button icons in the 2nd class (the usercontrol class) */

class check
    {
        bool t = false;
        bool change = false;
        Button b;
        public void changecolor() {
         //   btn.Image = global::Practice.Properties.Resources.Untitled_1;
            while(true){
                Console.WriteLine("ahha");
                if (t)
                {
                    if (change)
                    {
                     b.Image = global::CafeMonitorSystem.Properties.Resources.logon;
                        change = false;
                    }
                    else
                    {
                b.Image = global::CafeMonitorSystem.Properties.Resources.Untitled_1;
                        change = true;
                    }
                }
                Thread.Sleep(300);
            }
       
     
        }
        public bool isChange {
            get{ return t;}
            set{ 
             t= value;
             change = value;
            }
        }
        public Button getButton {
            get {return b;}
            set {b = value;}        
        }      
    }

So the problem is the UserControl class that contains the "Main Thread". It keeps on running even when the main form is closed.

How can I terminate it when I close the form?

Any help is greatly appreciated.
Posted
Updated 5-Apr-11 0:07am
v2

Your secondary threads are still running and the main thread will only exit once these thread(s) have finished what they needed to do.

Because you have infinite loop while (true)... that thread will never exit so you will need to stop it.

Here is some code to stop it.

C#
public partial class Monitor : UserControl
    {
        check chk = new check();
        public static Thread thread;
        public Monitor()
        {
            InitializeComponent();
            thread = new Thread(chk.changecolor);
            chk.getButton = this.button1;
            thread.Start();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            chk.isChange = true;
        }

    //HERE IS THE STOP CODE
     public void StopThread()
     {
        //this will let the thread exit gracefully
        chk._CanRun = false;
     }
    }


Also, you need to change your infinite loop

try something like this

class check
    {
        bool t = false;
        bool change = false;
        public bool _CanRun = true;//HERE ADDED THIS
        Button b;
        public void changecolor() {
         //   btn.Image = global::Practice.Properties.Resources.Untitled_1;
           
            while (_CanRun)
            {
                //do what you need todo

               
                Thread.Sleep(300);//here you could use AutoResetEvent with the Set method to avoid
                                  //having to wait, you can also use Thread.Abort but that will cause an 
                                  //exception
            }
       
     
        }
        public bool isChange {
            get{ return t;}
            set{ 
             t= value;
             change = value;
            }
        }
        public Button getButton {
            get {return b;}
            set {b = value;}        
        }      
    }


This will let the thread exit gracefully.

Here you should call the stopThread from the main from

C#
//you should add this using
        //using System.Collections.Generic;
        private List<monitor> MonitorList = new List<monitor>();

            /* This is the Main form that is being displayed and it contains a flowlayout */
        public Main()
        {
            InitializeComponent();

            
            //this event can be added using your property tab/events of the form.
            this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(Main_FormClosing);


            /* a flowlayoutpanel attached at the main form */
            flowLayoutPanel1.AutoScroll = true;
            flowLayoutPanel1.Dock = DockStyle.Fill;

            Monitor oMonitorTemp = null;

            for (int i = 0; i < 10; i++)
            {
                oMonitorTemp = new Monitor();

                //flowLayoutPanel1.Controls.Add(createButton((i+1) + ""));
                flowLayoutPanel1.Controls.Add(oMonitorTemp);

                //adding to list to be able to keep track of all objects
                //you can also go through all the controls in flowLayoutPanel1 
                //and check which ones are of type Monitor
                MonitorList.Add(oMonitorTemp);

            }


        }

        private void Main_FormClosing(object sender, FormClosingEventArgs e)
        {
            foreach (Monitor mon in MonitorList)
            {
                mon.StopThread();
            }

        }
/*End of main form */
</monitor></monitor>


You should also look at AutoResetEvent

Try this link -> http://msdn.microsoft.com/en-us/library/system.threading.autoresetevent.aspx[^]

Regards

Terence
 
Share this answer
 
v6
Comments
Olivier Levrey 5-Apr-11 7:51am    
From MSDN: http://msdn.microsoft.com/en-us/library/system.threading.thread.isbackground.aspx Background threads are identical to foreground threads, except that background threads do not prevent a process from terminating.
SwitcherSoft 5-Apr-11 8:06am    
I agree, just wanted to point out that using while(true) would not be a good practice. But yes, The difference between a background thread and a foreground thread is pretty simple. When the last foreground thread of a process is stopped, then the process terminates. There could be zero, 1 or an infinite number of background threads and they have no vote in whether a process terminates or not. So when the last foreground thread stops, then all background threads are also stopped and the process is stopped.
Olivier Levrey 5-Apr-11 9:20am    
You are absolutely right. I thought you voted 1 on my answer because you didn't know IsBackground property. That's why I wrote this comment: sorry for that.
I voted 4 before because I didn't think it was the best solution, but you gave good advices so I will change my mind and vote a 5 ;)
Manfred Rudolf Bihy 5-Apr-11 8:38am    
My 5+!
Madzmar25 5-Apr-11 21:35pm    
Where can i put or call the stopThread()? where should i place it or how do i invoke it?
Do this before starting the thread:
C#
thread.IsBackground = true;


From MSDN: Background threads are identical to foreground threads, except that background threads do not prevent a process from terminating.
http://msdn.microsoft.com/en-us/library/system.threading.thread.isbackground.aspx[^]

But be careful about your thread function. You shouldn't change or use any UI controls from a different thread. Have a look to InvokeRequired, Invoke and BeginInvoke.
 
Share this answer
 
v2
Comments
Madzmar25 5-Apr-11 6:19am    
What do you mean i shouldnt change or use any UI controls in different thread?
Olivier Levrey 5-Apr-11 6:24am    
You can't change them directly. Instead of writing b.Image = ... in your thread function, you should write something like b.Invoke((Action)(() => b.Image = ...));.
The Invoke (or BeginInvoke) methods execute a function on the proper thread (the one which created the control).
Madzmar25 5-Apr-11 6:20am    
Well this thread is responsible for changing the property of the button in the 2nd class or the UserControl class... it changes its icon image...
Olivier Levrey 5-Apr-11 6:25am    
Have a look to that page for example: http://msdn.microsoft.com/en-us/library/ms171728(v=vs.80).aspx
SwitcherSoft 5-Apr-11 8:08am    
This will solve it, only make a thread background if it does not do any critical operation. vote of 5 from me Olivier
Use Application.Exit[^] method for closing the application.
 
Share this answer
 
Comments
SwitcherSoft 5-Apr-11 7:11am    
This will not help, as the secondary thread will still be running. Except of course if you set it to be a background thread.
Manfred Rudolf Bihy 5-Apr-11 8:39am    
course instead of coarse!
FTFY
SwitcherSoft 5-Apr-11 9:55am    
Thanks =)

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900