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