CancellationTokenSource - Stream - problem

Noah Aas 1,210 Reputation points
2025-10-28T11:35:03.65+00:00

I want an event when the disconnect button is pressed or the server closes.

I can't get into the cancellation. Why? What's wrong?

The problem is

I can't get there. Disconnect and abort.

Why not? What's wrong?

         try      
          {   
             // MyCancellationTokenSource = new CancellationTokenSource();
             // while (true) //stream.DataAvailable) //(true)
             while (MyCancellationTokenSource.IsCancellationRequested) //stream.DataAvailable) //(true)
             {
                 int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, MyCancellationTokenSource.Token);

 public class MyTcpClient
 {
     private TcpClient _client;


     CancellationTokenSource MyCancellationTokenSource = new CancellationTokenSource();

     public event EventHandler<string> MessageReceived;

     /// <summary>
     /// Connect to the TCP server
     /// </summary>
     /// <param name="ipAddress"></param>
     /// <param name="port"></param>
     public void Connect(string ipAddress, int port)
     {
         _client = new TcpClient();
         _client.Connect(ipAddress, port);

         // Start a separate task to receive data
         _ = ReceiveDataAsync();

         // _ = Task.Run(async () => await ReceiveDataAsync());
     }

     /// <summary>
     /// Send message to the connected server
     /// </summary>
     /// <param name="message"></param>
     public void SendMessage(string message)
     {
         NetworkStream stream = _client.GetStream();
         byte[] buffer = Encoding.ASCII.GetBytes(message);
         stream.Write(buffer, 0, buffer.Length);
     }

     /// <summary>
     /// Handle incoming data from the server
     /// </summary>
     private async Task ReceiveDataAsync()
     {
         NetworkStream stream = _client.GetStream();
         byte[] buffer = new byte[1024];
         StringBuilder messageBuilder = new StringBuilder();

         try
         {
             //MyCancellationTokenSource = new CancellationTokenSource();
             while (true) //stream.DataAvailable) //(true)
             {
                 int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, MyCancellationTokenSource.Token);

                 if (bytesRead == 0)
                 {
                     break; // Server or client disconnected
                 }

                 string data = Encoding.ASCII.GetString(buffer, 0, bytesRead);
                 messageBuilder.Append(data);

                 if (data.Length > 0)
                 {
                     string receivedMessage = messageBuilder.ToString();
                     OnMessageReceived(receivedMessage);
                     messageBuilder.Clear();
                 }
             }

             _client.Close();
         }
         catch (OperationCanceledException)
         {
             Console.WriteLine("Cancel XXXX");
         }
     }

     public void Disconnect()
     {
         MyCancellationTokenSource.Cancel();

         _client?.Close();
     }

     protected virtual void OnMessageReceived(string message)
     {
         MessageReceived?.Invoke(this, message);
     }
 }

Developer technologies | C#
Developer technologies | C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
{count} votes

Answer accepted by question author
  1. Bruce (SqlWork.com) 81,606 Reputation points Volunteer Moderator
    2025-10-29T23:26:38.3666667+00:00

    you are using the default stream implementation, which does nothing when the token is canceled (thus no error thown). to get the read to exit, you close the socket as your Disconnect code does. just add the error throw.

    var token = MyCancellationTokenSource.Token;
    int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, token);
    token.ThrowIfCancellationRequested();
        
    

1 additional answer

Sort by: Most helpful
  1. Surya Amrutha Vaishnavi Lanka (INFOSYS LIMITED) 965 Reputation points Microsoft External Staff
    2025-10-29T04:01:47.4+00:00

    Thanks for reaching out! 

    1.  Make sure the stream is still open when you cancel. If you close the stream before cancellation, ReadAsync may exit silently without throwing.
    2. Add a Disconnect Event, then call OnDisconnected() in both places:
    • After bytesRead == 0
    • Inside catch (OperationCanceledException)

         3.Update your loop to handle both cancellation and disconnectionThanks for reaching out! 


Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.