Reputation: 5879
I have a simple WinForms app that is to serve as a server for multiple TelNet clients. When each one of these clients connects then a new thread is created. This is all working fine. However, I haven't found a suitable way to close these threads when I need to.
All the examples I have found online use Thread.Abort
(which I know is a bad idea) or deal with threads created from the same class, which isn't what I need to do.
This is a simplified version of my classes:
Main UI class:
private void btnStart_Click(object sender, EventArgs e)
{
_listener = new TelNetListener(_deviceConnection);
}
private void btnStop_Click(object sender, EventArgs e)
{
// NEED TO SIGNAL Listener and all Client threads to stop here.
}
Listener class (thread created from Main UI class):
public TelNetListener(DeviceConnection deviceConnection)
{
Thread thread = new Thread(() => TelNetListenerStart(deviceConnection));
thread.Start();
}
private void TelNetListenerStart(DeviceConnection deviceConnection)
{
Socket listener;
listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
listener.Bind(ipEndPoint);
listener.Listen(100);
_allDone = new ManualResetEvent(false);
while (true)
{
_allDone.Reset();
listener.BeginAccept(new AsyncCallback(AcceptCallBack), listener);
_allDone.WaitOne();
}
}
private void AcceptCallBack()
{
telNetClient = new TelNetClient(clientSocket, string.Format("ACTN{0}",
_clientCounter.ToString("D4")));
}
Client class (thread created from Listener class):
public TelNetClient(Socket socket, string clientName)
{
Thread thread = new Thread(() => TelNetClientStart(socket, clientName));
thread.Start();
}
private void TelNetClientStart(Socket socket, string clientName)
{
DeviceConnection deviceConnection = new DeviceConnection();
this.ClientName = clientName;
this.State = new StateObject();
this.State.WorkSocket = socket;
Send(this.State, "Welcome...");
this.State.WorkSocket.BeginReceive(this.State.Buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallBack), this.State);
}
Bare in mind there is a fair amount of code missing, so if there are undeclared variables or anything like that, just ignore them. I just didn't want to put in loads of irrelevant code.
I have seen examples using a ManualResetEvent
which seems to be what I need to do, but I'm not sure where to place it so that all the threads will work off it. Maybe I need 2, one for the Main
class to signal the Listener
class and from there another to signal all the Client
classes?
Could anyone help me with this please as it is pretty much the last part of the infrastructure needed for this project.
If you need any more information I will try and provide it.
Upvotes: 2
Views: 79
Reputation: 3686
Change the code:
while (true)
{
_allDone.Reset();
listener.BeginAccept(new AsyncCallback(AcceptCallBack), listener);
_allDone.WaitOne();
}
with some variable in your class which you can set.
while (this.Work)
{
_allDone.Reset();
listener.BeginAccept(new AsyncCallback(AcceptCallBack), listener);
_allDone.WaitOne();
}
When you want to stop a listener you simply set the Work property to false.
Upvotes: 2