Stopping all threads

M

MSDousti

Hi
I have written a VB .NET app, which uses several threads. I thought
that when the user closes the main window (when MainForm.closed event
occures, and I call application.exit) all running threads must abort,
but to my great surprise, running threads do not stop when
application.exit is called. So I (or the users) have to stop threads
using Ctrl-Alt-Del.

Is there a way to stop ALL threads with a single instruction, without
having to run Thread.abort on each single thread?

thnx in advance,
and sorry for grammatical errors.
 
A

Armin Zingler

MSDousti said:
Hi
I have written a VB .NET app, which uses several threads. I
thought that when the user closes the main window (when
MainForm.closed event occures, and I call application.exit) all
running threads must abort, but to my great surprise, running threads
do not stop when application.exit is called.

An application ends as soon as _all_ threads in the application have ended.
The thread creating the main form is only one of them.
So I (or the users) have
to stop threads using Ctrl-Alt-Del.

Is there a way to stop ALL threads with a single instruction,
without having to run Thread.abort on each single thread?

End


Usually, you should *not* use the End statment! You'd better initiate the
controlled end of the threads by setting a flag checked within the thread,
or, if the latter is not possible, call the thread's abort method.
 
C

Codemonkey

There are two types of threads, Background threads and Foreground threads.

Foreground threads will only exit when they have finished or have been
aborted.
Background threads will exit as soon as the last foreground thread has
exited.

Usually, foreground threads are used to handle user interface stuff (and
thus keep the application alive while they are running). Background threads
are used to perform tasks that can be interrupted when the main application
exits.

When launching threads, use the IsBackground property to tell the thread
what type it is.

When all foreground threads exit, the CLR will abort each background thread,
so be prepared to catch "ThreadAbortedException" exceptions.

Hope this helps,

Trev.
 
T

Tom Shelton

Hi
I have written a VB .NET app, which uses several threads. I thought
that when the user closes the main window (when MainForm.closed event
occures, and I call application.exit) all running threads must abort,
but to my great surprise, running threads do not stop when
application.exit is called. So I (or the users) have to stop threads
using Ctrl-Alt-Del.

Is there a way to stop ALL threads with a single instruction, without
having to run Thread.abort on each single thread?

thnx in advance,
and sorry for grammatical errors.

As Codemonkey said - foreground threads (which are the default type)
will not exit until they have been aborted or completed - and an
application will not exit until all foreground threads have exited.

It is possible to set the IsBackground property, so that the thread will
be a background thread. Background threads will abort as soon as the
last foreground thread has exited - in other words, they won't keep the
application alive....

Personally, I don't like the idea of having threads forcibly closed at
the end of the application - so I tend not to use Background threads. I
have taken several approaches to this problem myself - but my current
solution I'm working on for simple threads is to inherit a worker thread
class from a class that looks like this... (Sorry for the C# code - but
that's what I do - it should be fairly easy to convert this to VB.NET
though :)

using System;
using System.Threading;

namespace FireAnt.Threading
{
public abstract class WorkerThreadBase : IDisposable
{

private Thread worker;
private ManualResetEvent waitHandle;
private object terminateLock;
private bool terminate;

// make sure that derived classes call one of the
// defined constructors
private WorkerThreadBase() {}

// various constructors
public WorkerThreadBase(string name) : this(name, false, ApartmentState.MTA) {}
public WorkerThreadBase(string name, bool autoStart) : this(name, autoStart, ApartmentState.MTA) {}
public WorkerThreadBase(string name, ApartmentState apartmentState) : this(name, false, apartmentState) {}

// this is the bad boy!
public WorkerThreadBase(string name, bool autoStart, ApartmentState apartmentState)
{
if (name != null && name.Length > 0 )
{
// create some internal objects
this.waitHandle = new ManualResetEvent(false);
this.terminateLock = new object();

// create a new thread and set some initial defaults.
this.worker = new Thread(new ThreadStart(this.ThreadMethod));

this.worker.Name = name;
this.worker.ApartmentState = apartmentState;
if (autoStart)
{
this.Start();
}
}
else
{
throw new ArgumentException("Name can not be null or empty", "name");
}
}

~WorkerThreadBase()
{
this.Stop(true);
this.waitHandle.Close();
}

/// <summary>
/// Get/Set the value of the threads name
/// </summary>
public string Name
{
get
{
return worker.Name;
}
set
{
worker.Name = value;
}
}

public WaitHandle WaitHandle
{
get
{
return this.waitHandle;
}
}

public virtual void Start()
{
this.worker.Start();
}

public virtual void Stop(bool wait)
{
if (this.worker.IsAlive)
{
this.Terminate = true;

if (wait)
{
this.worker.Join();
}
}
}

protected bool Terminate
{
get
{
bool result = false;

// create a criticle section here...
Monitor.Enter(this.terminateLock);
result = this.terminate;
Monitor.Exit(this.terminateLock);

return result;
}
set
{
// create a criticle section here...
Monitor.Enter(this.terminateLock);
this.terminate = value;
Monitor.Exit(this.terminateLock);
}
}

private void ThreadMethod()
{
try
{
// call the work method...
this.Work();
}
catch
{
// TODO: RAISE AN EVENT?
}
finally
{
// signal that we are teminating...
this.waitHandle.Set();
}
}

protected abstract void Work();

#region IDisposable Members

public void Dispose()
{
this.Stop(true);
this.waitHandle.Close();
GC.SuppressFinalize(this);
}

#endregion
}
}

This is still a work in progress, so I haven't worked out all the
details yet. It is sort of a starting point for a simplfied threading
framework. That's the reason to force the name for the thread. I'm
planning a collection class that probably will inherit from
DictionaryBase that will make management of groups of threads a little
simpler :) I got the idea for the class from an article I read
a couple of weeks ago - unfortunately, I can't remember where.

Anway the idea is that you can then use it like this:

public class Worker : WorkerThreadBase
{

// define a constructor
Worker(string name, bool autoStart) : base(name, autoStart)
{
}

// override the work method
public override void Work()
{
int i = 0;
while (!this.Terminate)
{
Console.WriteLine("{0} - {1}", this.Name, i);
Thread.Sleep(100);
i++;
}
}

public static void Main()
{
// create and start the threads
Worker w1 = new Worker("John", true);
Worker w2 = new Worker("Mary", true);

// wait for a while
Console.ReadLine();

// stop them async
w1.Stop(false);
w2.Stop(false);

// wait for all threads to complete
WaitHandle.WaitAll(new WaitHandle[] {w1.WaitHandle, w2.WaitHandle});

// dispose unmanaged resources.
w1.Dispose();
w2.Dispose();
}
}

Anyway, maybe this will give you a starting point for your own threading
framework.
 
M

MSDousti

Hi,
thank u very much.
I found ur answers very useful, and it was of greatest help to me.
good luck.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top