0

I have a C# windows application in which I create an instance of a some class, in which it has a member which is a window form and this form has a button that when I click it I open a new form that can run a worker thread, let's say:

public static void Main()
{
    MyClass mc = new MyClass();
    mc.ShowForm();
}

in MyClass.cs:

public void ShowForm()
{
    MyFirstForm firstForm = new MyFirstForm();
    firstForm.Show();
}

in MyFirstForm.cs:

private void myButton_Click(object sender, EventArgs e)
{
    MySecondForm secondForm =  new MySecondForm();
    secondForm.Show();
}

in MySecondForm.cs:

private void startButton_Click(object sender, EventArgs e)
{
    var worker = new Thread(StartWork);
    worker.Start();
}

private void stopButton_Click(object sender, EventArgs e)
{
    m_stopped = true;
}

private void StartWork()
{
    while(!m_stopped)
    {
       //work...
    }
}

When I run my app, clicks myButton, then click startButton, and then exit my app (I have a tray Icon that when clicked to exit, call base.Shutdown() ), the second form stays hanging and non responsive.

My original question was, what is the best way to notify the second form that it should close and stop the running thread, but during writing this post I noticed that I can use Task.Factory.StartNew(StartWork); and when I tried it, it worked without a hitch. So now I have another question which is why is this happening?

I tried registering to Closing , Closed , FormClosing events and setting m_stopped = true but they were not getting called.

EDIT: As @drf suggested the thread is a foreground thread hence the app is blocked while it runs, so adding:

worker.IsBackground = true;

fixed it.

ZivS
  • 2,094
  • 2
  • 27
  • 48
  • set its parent - `.Show(this)`, all child forms should get closed with their parent – Sayse Sep 01 '14 at 06:18
  • You could track `Form Closing` event and close the running thread. – Hassan Sep 01 '14 at 06:22
  • Would setting the [`IsBackground`](http://msdn.microsoft.com/en-us/library/system.threading.thread.isbackground(v=vs.110).aspx) property on the thread to true work? – drf Sep 01 '14 at 06:28
  • @drf - Yes that actually did work. I don't understand why is `Closing` not being triggered? – ZivS Sep 01 '14 at 06:46
  • @ShaZiv, can you show how you are registering to `FormClosing` event? – Hassan Sep 01 '14 at 06:56
  • @HassanNisar - It is triggered when I actually close (X) the form... but anyway: `FormClosing += OnFormClosing; private void OnFormClosing(object sender, FormClosingEventArgs formClosingEventArgs) { //...}` – ZivS Sep 01 '14 at 06:58
  • @ShaZiv. I see you make Forms objects, I hope you have add like for second form it should be `secondForm.FormClosing += new FormClosingEventHandler(secondForm_FormClosing);` – Hassan Sep 01 '14 at 07:11
  • @HassanNisar you're getting off the subject. I know how to register to events, and as I've said it's working when I hit the X button. The += I have is in the c'tor and your `new FormClosingEventHandler` statement is redundant since compiler deduce the type by itself. My question is more about the thread issue... – ZivS Sep 01 '14 at 07:58
  • @ShaZiv. Ok no offense. I was looking at form objects with no event handlers. Let's wait for some other fellow. Good luck. – Hassan Sep 01 '14 at 08:14

2 Answers2

1

Your thread is currently a foreground thread which will prevent the process from exiting until the thread finishes. http://msdn.microsoft.com/en-us/library/system.threading.thread.isbackground(v=vs.110).aspx

Change your thread startup code to this:

private void startButton_Click(object sender, EventArgs e)
{
    var worker = new Thread(StartWork);
    worker.IsBackground = true;
    worker.Start();
}
jaket
  • 9,140
  • 2
  • 25
  • 44
  • That's great. Have you tried it? If so would you please update the code in your post to show it? Otherwise, someone who has worked with .net threading much is immediately going to draw the same conclusion I have. – jaket Sep 02 '14 at 15:18
0

I think for closing application you should use Application.Exit Method:

It informs all message pumps that they must terminate, and then closes all application windows after the messages have been processed.

Also you could track FormClosing event of each form. Check if Thread.IsAlive then Thread.Abort() or cancel closing.

Hassan
  • 5,360
  • 2
  • 22
  • 35
  • No, definitely not, Application.Exit misses out important closure steps. – Sayse Sep 01 '14 at 06:40
  • @Sayse. You mean closing of individual forms? – Hassan Sep 01 '14 at 06:43
  • ["The Exit method does not raise the Closed and Closing events.."](http://msdn.microsoft.com/en-us/library/ms157894(v=vs.110).aspx), I'm sure there is more to it as well – Sayse Sep 01 '14 at 06:46
  • It is same link as I mentioned in the post. Can you check remarks section. – Hassan Sep 01 '14 at 06:48
  • Closed and Closing events are obsolete method. Which are different. – Hassan Sep 01 '14 at 06:49
  • Can you? "If one of more of the handlers cancels the event, then Exit returns without further action. Otherwise, a FormClosed event is raised.." - It isn't guarranteed to close correctly. – Sayse Sep 01 '14 at 06:50
  • Yes. That is what they are mentioning about FormClosing event. If you cancel closing then it will not call `FormClosed` event. – Hassan Sep 01 '14 at 06:53
  • I don't want to say any more about this, Marc Gravell gives a light explanation [here](http://stackoverflow.com/a/1057159/1324033) stating there are better ways which is what I was aiming to point out. – Sayse Sep 01 '14 at 07:00
  • Thank you @Sayse, I usually learn a lot from your answers. I will study it. – Hassan Sep 01 '14 at 07:14