Skip to content

@StephenCleary /Example Output
Last active

Embed URL

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Simple WebAPI app with Console client that shows that async methods do release threads to the thread pool.
Synchronous time for 8 connections: 00:00:01.0194025
Synchronous time for 9 connections: 00:00:02.0362007
Asynchronous time for 8 connections: 00:00:01.0413737
Asynchronous time for 9 connections: 00:00:01.0238674
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
namespace MvcApplication2
{
// Note: For instructions on enabling IIS6 or IIS7 classic mode,
// visit http://go.microsoft.com/?LinkId=9394801
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
// Begin Changes
int workerThreads, ioThreads;
ThreadPool.GetMaxThreads(out workerThreads, out ioThreads);
ThreadPool.SetMaxThreads(Environment.ProcessorCount, ioThreads);
// End Changes
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
}
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
class Program
{
static void Main(string[] args)
{
try
{
MainAsync().Wait();
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Console.ReadKey();
}
static async Task MainAsync()
{
ServicePointManager.DefaultConnectionLimit = int.MaxValue;
int connections;
var syncUrl = "http://localhost:35697/api/values/";
var asyncUrl = "http://localhost:35697/api/values/13";
connections = Environment.ProcessorCount;
Console.WriteLine(" Synchronous time for " + connections + " connections: " +
await RunTest(syncUrl, connections));
connections = Environment.ProcessorCount + 1;
Console.WriteLine(" Synchronous time for " + connections + " connections: " +
await RunTest(syncUrl, connections));
connections = Environment.ProcessorCount;
Console.WriteLine("Asynchronous time for " + connections + " connections: " +
await RunTest(asyncUrl, connections));
connections = Environment.ProcessorCount + 1;
Console.WriteLine("Asynchronous time for " + connections + " connections: " +
await RunTest(asyncUrl, connections));
}
static async Task<TimeSpan> RunTest(string url, int concurrentConnections)
{
var sw = new Stopwatch();
var client = new HttpClient();
await client.GetStringAsync(url); // warmup
sw.Start();
await Task.WhenAll(Enumerable.Range(0, concurrentConnections).Select(i => client.GetStringAsync(url)));
sw.Stop();
return sw.Elapsed;
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http;
namespace MvcApplication2.Controllers
{
public class ValuesController : ApiController
{
// Synchronous
public IEnumerable<string> Get()
{
Thread.Sleep(1000);
return new string[] { "value1", "value2" };
}
// Asynchronous
public async Task<IEnumerable<string>> Get(int id)
{
await Task.Delay(1000);
return new string[] { "value1", "value2" };
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.