title: How to pass CancellationToken to an EventHandler
body: <p>Having below reference code for Async TCP server, I want to pass CancellationToken to <code>OnDataReceived</code>:</p>
  
  <pre class="lang-cs prettyprint-override"><code>public sealed class TcpServer : IDisposable
      {
          private readonly TcpListener _listener;
          private CancellationTokenSource _tokenSource;
          private CancellationToken _token;
          private bool _listening;
  
  
          public event EventHandler&lt;ConnectedEventArgs&gt; OnDataReceived;
  
          public TcpServer(IPAddress address, int port)
          {
              _listener = new TcpListener(address, port);
          }
  
  
          public async Task StartAsync(CancellationToken? token = null)
          {
              _tokenSource = CancellationTokenSource.CreateLinkedTokenSource(token ?? new CancellationToken());
              _token = _tokenSource.Token;
              _listener.Start();
              _listening = true;
  
              try
              {
                  while (!_token.IsCancellationRequested)
                  {
                      await Task.Run(async () =&gt;
                      {
                          var tcpClientTask = _listener.AcceptTcpClientAsync();
                          var tcpClient = await tcpClientTask;
  
                          OnDataReceived?.Invoke(tcpClient, new ConnectedEventArgs(tcpClient.GetStream()));
                      }, _token);
                  }
              }
  
              finally
              {
                  _listener.Stop();
                  _listening = false;
              }
          }
  
          public void Stop()
          {
              _tokenSource?.Cancel();
          }
  
          public void Dispose()
          {
              Stop();
          }
      }
  
      public class ConnectedEventArgs : EventArgs
      {
          public NetworkStream Stream { get; private set; }
  
          public ConnectedEventArgs(NetworkStream stream)
          {
              Stream = stream;
          }
      }
  </code></pre>
  
  <p>The following code, shows how I am consuming the above code, currently in <code>ReadStreamBytesAsync</code> I am passing <code>new CancellationToken()</code> instead I want to pass the <code>token</code> argument from <code>MainAsync</code>:</p>
  
  <pre class="lang-cs prettyprint-override"><code>class Program
      {
          static void Main(string[] args)
          {
              InitAsyncWork();
  
              Console.WriteLine("ended.");
              Console.ReadKey();
          }
  
          static void InitAsyncWork()
          {
              var cts = new CancellationTokenSource();
              Console.CancelKeyPress += (s, e) =&gt;
              {
                  e.Cancel = true;
                  cts.Cancel();
              };
              MainAsync(cts.Token).GetAwaiter().GetResult();
          }
          static async Task MainAsync(CancellationToken token)
          {
              using (var server = new TcpServer(IPAddress.Any, 54001))
              {
                  server.OnDataReceived += TcpClientOnlyReceive;
                  await server.StartAsync(token);
              }
          }
  
          private static async void TcpClientOnlyReceive(object sender, ConnectedEventArgs e)
          {
              try
              {
                  using (TcpClient client = (TcpClient)sender)
                  using (NetworkStream stream = e.Stream)
                  {
                      while (Utilities.IsTcpClientConnected(client))
                      {
                          if (client.Available == 0)
                          {
                              await Task.Delay(50);
                              continue;
                          }
  
                          byte[] rawX = await ReadStreamBytesAsync(stream, client.ReceiveBufferSize, new CancellationToken());
  
                      }//while(client.Connected)
  
                  }//using(client)using(stream)
  
              }
              catch (Exception ex)
              {
                  Utilities.logger.Error("TcpClientOnlyReceive():Exception!!\r\nMsg: {1}\r\nStack: {2}", ex.Message, ex.StackTrace);
              }
          }
  
          private static async Task&lt;byte[]&gt; ReadStreamBytesAsync(NetworkStream stream, int maxBytesToRead, CancellationToken token)
          {
              var bytesRead = 0;
              var totalBytesRead = 0;
              var clientMsg = new byte[maxBytesToRead];
              byte[] contentBytes;
              using (MemoryStream ms = new MemoryStream())
              {
                  do
                  {
                      bytesRead = await stream.ReadAsync(clientMsg, totalBytesRead, clientMsg.Length - totalBytesRead, token);
                      await ms.WriteAsync(clientMsg, totalBytesRead, bytesRead, token);
                      totalBytesRead += bytesRead;
                  }
                  while (bytesRead &gt; 0 &amp;&amp; stream.DataAvailable);
                  contentBytes = ms.ToArray();
              }
              return contentBytes;
          }
  
      }
  </code></pre>
  
  <p>Should I define <code>cts</code> as global variable? Or modify <code>ConnectedEventArgs</code> class so that it accept CancellationToken as property ?</p>
  
  <p><strong>Clarifications:</strong>
  Based on the received comments and 1 vote to close the question!</p>
  
  <ol>
  <li>My main objective is to close the application once the user press <code>ctrl+c</code>, currently that's prevent accepting new connections but it won't cancel the established connections.</li>
  <li>I never heard of Tasks meant to replace events, if that's true, please share a reference.</li>
  <li>It will be great to share better version of the code, if its BAD design! <em>personally I think its clean and robust</em>.  </li>
  </ol>