Cancelar o bloqueio da chamada AcceptTcpClient
Como todos já devem saber, a maneira mais simples de aceitar conexões TCP de entrada em C # é fazendo um loop através de TcpListener.AcceptTcpClient (). Além disso, esse modo bloqueará a execução do código até que uma conexão seja obtida. Isso é extremamente limitante para uma GUI, então eu quero ouvir conexões em um thread ou tarefa separada.
Foi-me dito, que os tópicos têm várias desvantagens, no entanto, ninguém me explicou o que são. Então, ao invés de usar threads, eu usei tarefas. Isso funciona muito bem, no entanto, como o método AcceptTcpClient está bloqueando a execução, não consigo encontrar nenhuma maneira de manipular um cancelamento de tarefa.
Atualmente, o código se parece com isso, mas não tenho idéia de como gostaria de cancelar a tarefa quando quiser que o programa pare de ouvir as conexões.
Primeiro, a função executada na tarefa:
static void Listen () {
// Create listener object
TcpListener serverSocket = new TcpListener ( serverAddr, serverPort );
// Begin listening for connections
while ( true ) {
try {
serverSocket.Start ();
} catch ( SocketException ) {
MessageBox.Show ( "Another server is currently listening at port " + serverPort );
}
// Block and wait for incoming connection
if ( serverSocket.Pending() ) {
TcpClient serverClient = serverSocket.AcceptTcpClient ();
// Retrieve data from network stream
NetworkStream serverStream = serverClient.GetStream ();
serverStream.Read ( data, 0, data.Length );
string serverMsg = ascii.GetString ( data );
MessageBox.Show ( "Message recieved: " + serverMsg );
// Close stream and TcpClient connection
serverClient.Close ();
serverStream.Close ();
// Empty buffer
data = new Byte[256];
serverMsg = null;
}
}
Em segundo lugar, as funções que iniciam e param o serviço de escuta:
private void btnListen_Click (object sender, EventArgs e) {
btnListen.Enabled = false;
btnStop.Enabled = true;
Task listenTask = new Task ( Listen );
listenTask.Start();
}
private void btnStop_Click ( object sender, EventArgs e ) {
btnListen.Enabled = true;
btnStop.Enabled = false;
//listenTask.Abort();
}
Eu só preciso de algo para substituir a chamada listenTask.Abort () (que eu comentei porque o método não existe)