public MessageStreamListener(Uri[] urls, Func<WebClientWithTimeout, Uri, Uri> converter)
{
if (urls == null) throw new ArgumentNullException("urls");
if (urls.Length == 0) throw new ArgumentException("must specify at least 1 url");
this.urls = urls;
this.DeadTimeout = 2000;
this.uriConverter = converter;
// this holds the resolved urls, key is coming from the 'urls' array
this.realUrls = this.urls.Distinct().ToDictionary(u => u, u => (Uri)null);
this.RetryCount = 0;
this.RetryTimeout = new TimeSpan(0, 0, 0, 0, 500);
// domain unloads are not guaranteed to call the finalizers
// and when users do not abide the IDIsposabel contract
// we end up a job in the thread sockIOPool which never quits
// and prevents the unloading of the app domain
// this is not big deal in normal applications because the
// process exit aborts everything, but it's a huge issue in
// asp.net because the app domain will not be unloaded
// but still, the best way to deal with this is issue to dispose the memcachedClient
AppDomain.CurrentDomain.DomainUnload += CurrentDomain_DomainUnload;
}