THRIFT-5419 Incorrect usage of thread pool in TThreadPoolAsyncServer may lead to poor performance
Client: netstd
Patch: Nathan P Sharp, Jens Geyer

This closes #2395
diff --git a/lib/netstd/Thrift/Server/TThreadPoolAsyncServer.cs b/lib/netstd/Thrift/Server/TThreadPoolAsyncServer.cs
index 7a5254a..49593cc 100644
--- a/lib/netstd/Thrift/Server/TThreadPoolAsyncServer.cs
+++ b/lib/netstd/Thrift/Server/TThreadPoolAsyncServer.cs
@@ -178,7 +178,7 @@
                     try
                     {
                         TTransport client = await ServerTransport.AcceptAsync(cancellationToken);
-                        ThreadPool.QueueUserWorkItem(this.Execute, client);
+                        _ = Task.Run(async () => await ExecuteAsync(client), cancellationToken);  // intentionally ignoring retval
                     }
                     catch (TaskCanceledException)
                     {
@@ -219,11 +219,11 @@
         /// threadContext will be a TTransport instance
         /// </summary>
         /// <param name="threadContext"></param>
-        private void Execute(object threadContext)
+        private async Task ExecuteAsync(TTransport client)
         {
             var cancellationToken = ServerCancellationToken;
 
-            using (TTransport client = (TTransport)threadContext)
+            using (client)
             {
                 ITAsyncProcessor processor = ProcessorFactory.GetAsyncProcessor(client, this);
                 TTransport inputTransport = null;
@@ -242,12 +242,12 @@
 
                         //Recover event handler (if any) and fire createContext server event when a client connects
                         if (ServerEventHandler != null)
-                            connectionContext = ServerEventHandler.CreateContextAsync(inputProtocol, outputProtocol, cancellationToken).Result;
+                            connectionContext = await ServerEventHandler.CreateContextAsync(inputProtocol, outputProtocol, cancellationToken);
 
                         //Process client requests until client disconnects
                         while (!stop)
                         {
-                            if (! inputTransport.PeekAsync(cancellationToken).Result)
+                            if (! await inputTransport.PeekAsync(cancellationToken))
                                 break;
 
                             //Fire processContext server event
@@ -255,10 +255,10 @@
                             //That is to say it may be many minutes between the event firing and the client request
                             //actually arriving or the client may hang up without ever makeing a request.
                             if (ServerEventHandler != null)
-                                ServerEventHandler.ProcessContextAsync(connectionContext, inputTransport, cancellationToken).Wait();
+                                await ServerEventHandler.ProcessContextAsync(connectionContext, inputTransport, cancellationToken);
 
                             //Process client request (blocks until transport is readable)
-                            if (!processor.ProcessAsync(inputProtocol, outputProtocol, cancellationToken).Result)
+                            if (! await processor.ProcessAsync(inputProtocol, outputProtocol, cancellationToken))
                                 break;
                         }
                     }
@@ -274,7 +274,7 @@
 
                     //Fire deleteContext server event after client disconnects
                     if (ServerEventHandler != null)
-                        ServerEventHandler.DeleteContextAsync(connectionContext, inputProtocol, outputProtocol, cancellationToken).Wait();
+                        await ServerEventHandler.DeleteContextAsync(connectionContext, inputProtocol, outputProtocol, cancellationToken);
 
                 }
                 finally