/// <summary> /// Concurrently requests the given <paramref name="target"/> <paramref name="requestCount"/> times. /// </summary> /// <param name="target">Uri to torture.</param> /// <param name="requestCount">Number of requests.</param> /// <param name="concurrentRequestLimit">Maximum number of concurrent requests.</param> public static async Task<TortureResult> TortureAsync(Uri target, Int64 requestCount, Int64 concurrentRequestLimit = 22) { Int64 bytesRead = 0; Stopwatch stopwatch = Stopwatch.StartNew(); var pendingTasks = new List<Task<Byte[]>>(); using (HttpClient client = new HttpClient()) { for (Int64 index = 0; index < requestCount; index++) { Task<Byte[]> fetchTask = client.GetByteArrayAsync(target); pendingTasks.Add(fetchTask); if (pendingTasks.Count > concurrentRequestLimit) { foreach (var task in pendingTasks.ConsumeWhere(null)) { Byte[] result = await task.ConfigureAwait(false); bytesRead += result.LongLength; } } } foreach (var task in pendingTasks.ConsumeWhere(null)) { Byte[] result = await task.ConfigureAwait(false); bytesRead += result.LongLength; } } return new TortureResult { Target = target, RequestCount = requestCount, BytesRead = bytesRead, TimeElapsed = stopwatch.Elapsed }; }
/// <summary> /// Listens for Http requests asynchronously on the <paramref name="host"/> and directs them to the <paramref name="routes"/>. /// </summary> /// <param name="host"></param> /// <param name="routes">Collection of routes that will serve requests.</param> /// <param name="cancellation">Cancellation token to stop listening (Optional).</param> public static async Task ListenForeverAsync(IReadOnlyCollection<Uri> endpoints, IReadOnlyCollection<Route> routes, CancellationToken cancellation = default(CancellationToken)) { HttpListener listener = new HttpListener(); listener.Prefixes.AddRange(endpoints.Select(ep => ep.ToString())); listener.Start(); List<Task> pendingTasks = new List<Task>(); try { while (true) { cancellation.ThrowIfCancellationRequested(); try { HttpListenerContext context = await listener.GetContextAsync().ConfigureAwait(false); // Begin serving the request. Task serveTask = ServeAsync(context, routes); pendingTasks.Add(serveTask); // Reap completed tasks and propagate exceptions. foreach (Task completedTask in pendingTasks.ConsumeWhere(task => task.IsCompleted)) { await completedTask.ConfigureAwait(false); } await serveTask; } catch (Exception ex) { Debug.WriteLine("HTTPServer caught exception:"); Debug.WriteLine(ex.ToString()); } } } finally { listener.Stop(); await Task.WhenAll(pendingTasks).ConfigureAwait(false); } }