Example #1
0
		public void Start(Func<SynchronizationContext> syncContext, int concurrentAccepts, int maxDelayMS = 0)
		{
			if (concurrentAccepts <= 0)
			{
				throw new ArgumentOutOfRangeException("concurrentAccepts", "Expected >0 concurrent accepts");
			}

			m_logger.Info("Listening on {0} with {1} concurrent accepts", m_listener.Prefixes.First(), concurrentAccepts);
			m_listener.Start();

			for (var i = 0; i < concurrentAccepts; i++)
			{
				var context = syncContext();
				var state = new EventLoopState(maxDelayMS);
				Task.Run(() => MainLoop(context, state));

				if (maxDelayMS > 0 && context is EventLoopContext)
					Task.Run(() => CalcDelay(context, state));
			}
		}
Example #2
0
		private async Task MainLoop(SynchronizationContext syncContext, EventLoopState state)
		{
			while (true)
			{
				try
				{
					HttpListenerContext context;
					try
					{
						context = await m_listener.GetContextAsync();
					}
					catch (ObjectDisposedException)
					{
						return;
					}
					catch (HttpListenerException ex)
					{
						// IO error due to our request, means we're probably exiting
						if (ex.NativeErrorCode == 995)
							continue;

						throw;
					}

					m_resetEvent.Wait();

					syncContext.Post(async unused =>
					{
						var wrapper = new Context(context);
						wrapper.Response.KeepAlive = m_keepAlive && wrapper.Request.KeepAlive;

						await m_processor.Process(wrapper, state.Delay > state.MaxDelay);
					}, null);
				}
				catch (Exception ex)
				{
					m_logger.Error("Error in accept loop: " + ex);
				}
			}
		}
Example #3
0
		private void CalcDelay(SynchronizationContext context, EventLoopState state)
		{
			context.Post(async unused =>
			{
				var timer = Stopwatch.StartNew();

				while (true)
				{
					// Yield back to the event loop
					await Task.Yield();

					// Find out how long it took for the event loop to handle our request
					var elapsed = (int)timer.ElapsedMilliseconds;

					state.Delay = elapsed;

					await Task.Delay(Math.Max(0, 500 - elapsed));
					timer.Restart();
				}
			}, null);
		}