throw new NotSupportedException (String.Format ("Channel type {0} is not supported", typeof (TChannel)));
}
+
+ protected override void OnAbort ()
+ {
+ HttpHandler.CloseServiceChannel ();
+ }
+
+ protected override void OnClose (TimeSpan timeout)
+ {
+ HttpHandler.CloseServiceChannel ();
+ base.OnClose (timeout);
+ }
}
internal abstract class HttpChannelListenerBase<TChannel> : InternalChannelListenerBase<TChannel>
get { return encoder; }
}
- protected IList<TChannel> Channels {
- get { return channels; }
- }
-
protected override TChannel OnAcceptChannel (TimeSpan timeout)
{
TChannel ch = CreateChannel (timeout);
- Channels.Add (ch);
return ch;
}
protected override void OnClose (TimeSpan timeout)
{
DateTime start = DateTime.Now;
- foreach (TChannel ch in new List<TChannel> (Channels)) // they will be removed during iteration, so create another one
- ch.Close (timeout - (DateTime.Now - start));
base.OnClose (timeout - (DateTime.Now - start));
}
}
Uri request_url;
ServiceHostBase host;
Queue<HttpContext> pending = new Queue<HttpContext> ();
- bool closing;
+ int close_state;
- AutoResetEvent wait = new AutoResetEvent (false);
+ AutoResetEvent process_request_wait = new AutoResetEvent (false);
AutoResetEvent listening = new AutoResetEvent (false);
public SvcHttpHandler (Type type, Type factoryType, string path)
public HttpContext WaitForRequest (TimeSpan timeout)
{
+ if (close_state > 0)
+ return null;
DateTime start = DateTime.Now;
+
+ if (close_state > 0)
+ return null;
+ if (pending.Count == 0) {
+ if (!process_request_wait.WaitOne (timeout - (DateTime.Now - start), false) || close_state > 0)
+ return null;
+ }
+ HttpContext ctx;
lock (pending) {
- if (pending.Count > 0) {
- var ctx = pending.Dequeue ();
- if (ctx.AllErrors != null && ctx.AllErrors.Length > 0)
- return WaitForRequest (timeout - (DateTime.Now - start));
- return ctx;
- }
+ if (pending.Count == 0)
+ return null;
+ ctx = pending.Dequeue ();
}
-
- return wait.WaitOne (timeout - (DateTime.Now - start), false) && !closing ?
- WaitForRequest (timeout - (DateTime.Now - start)) : null;
+ if (ctx.AllErrors != null && ctx.AllErrors.Length > 0)
+ return WaitForRequest (timeout - (DateTime.Now - start));
+ return ctx;
}
public void ProcessRequest (HttpContext context)
request_url = context.Request.Url;
EnsureServiceHost ();
pending.Enqueue (context);
+ process_request_wait.Set ();
- wait.Set ();
-
- listening.WaitOne ();
+ if (close_state == 0)
+ listening.WaitOne ();
}
public void EndRequest (HttpContext context)
listening.Set ();
}
+ // called from SvcHttpHandlerFactory's remove callback (i.e.
+ // unloading asp.net). It closes ServiceHost, then the host
+ // in turn closes the listener and the channels it opened.
+ // The channel listener calls CloseServiceChannel() to stop
+ // accepting further requests on its shutdown.
public void Close ()
{
- closing = true;
- listening.Set ();
- wait.Set ();
host.Close ();
host = null;
- closing = false;
+ }
+
+ // called from AspNetChannelListener.Close() or .Abort().
+ public void CloseServiceChannel ()
+ {
+ if (close_state > 0)
+ return;
+ close_state = 1;
+ process_request_wait.Set ();
+ listening.Set ();
+ close_state = 2;
}
void EnsureServiceHost ()
host = new ServiceHost (type, baseUri);
host.Extensions.Add (new VirtualPathExtension (baseUri.AbsolutePath));
- /*
- if (host.Description.Endpoints.Count == 0)
- //FIXME: Binding: Get from web.config.
- host.AddServiceEndpoint (ContractDescription.GetContract (type).Name,
- new BasicHttpBinding (), new Uri (path, UriKind.Relative));
-
- var c = host.BaseAddresses;
- */
-
host.Open ();
-
- //listening.WaitOne ();
}
}
}