views:

168

answers:

1

The following code is part of a WCF service. Will eventWatcher take up a thread in the ASP .NET thread pool, even if it is set IsBackground = true?

/// <summary>
/// Provides methods to work with the PhoneSystem web services SDK.
/// This is a singleton since we need to keep track of what lines (extensions) are open.
/// </summary>
public sealed class PhoneSystemWebServiceFactory : IDisposable
{
    // singleton instance reference
    private static readonly PhoneSystemWebServiceFactory instance = new PhoneSystemWebServiceFactory();
    private static readonly object l = new object();
    private static volatile Hashtable monitoredExtensions = new Hashtable();
    private static readonly PhoneSystemWebServiceClient webServiceClient = CreateWebServiceClient();
    private static volatile bool isClientRegistered;
    private static volatile string clientHandle;
    private static readonly Thread eventWatcherThread = new Thread(EventPoller) {IsBackground = true};

    #region Constructor
    // these constructors are hacks to make the C# compiler not mark beforefieldinit
    //  more info: http://www.yoda.arachsys.com/csharp/singleton.html
    static PhoneSystemWebServiceFactory()
    {
    }

    PhoneSystemWebServiceFactory()
    {
    }
    #endregion

    #region Properties
    /// <summary>
    /// Gets a thread safe instance of PhoneSystemWebServiceFactory
    /// </summary>
    public static PhoneSystemWebServiceFactory Instance
    {
        get { return instance; }
    }
    #endregion

    #region Private methods
    /// <summary>
    /// Create and configure a PhoneSystemWebServiceClient with basic http binding and endpoint from app settings.
    /// </summary>
    /// <returns>PhoneSystemWebServiceClient</returns>
    private static PhoneSystemWebServiceClient CreateWebServiceClient()
    {
        string url = ConfigurationManager.AppSettings["PhoneSystemWebService_Url"];
        if (string.IsNullOrEmpty(url))
        {
            throw new ConfigurationErrorsException(
                "The AppSetting \"PhoneSystemWebService_Url\" could not be found. Check the application configuration and ensure that the element exists. Example: <appSettings><add key=\"PhoneSystemWebService_Url\" value=\"http://xyz\" /></appSettings>");
        }

        return new PhoneSystemWebServiceClient(new BasicHttpBinding(), new EndpointAddress(url));
    }
    #endregion

    #region Event poller
    public static void EventPoller()
    {
        while (true)
        {
            if (Thread.CurrentThread.ThreadState == ThreadState.Aborted ||
                Thread.CurrentThread.ThreadState == ThreadState.AbortRequested ||
                Thread.CurrentThread.ThreadState == ThreadState.Stopped ||
                Thread.CurrentThread.ThreadState == ThreadState.StopRequested)
                break;

            // get events
            //webServiceClient.GetEvents(clientHandle, 30, 100);
        }

        Thread.Sleep(5000);
    }
    #endregion

    #region Client registration methods
    private static void RegisterClientIfNeeded()
    {
        if (isClientRegistered)
        {
            return;
        }

        lock (l)
        {
            // double lock check
            if (isClientRegistered)
            {
                return;
            }

            //clientHandle = webServiceClient.RegisterClient("PhoneSystemWebServiceFactoryInternal", null);
            isClientRegistered = true;
        }
    }

    private static void  UnregisterClient()
    {
        if (!isClientRegistered)
        {
            return;
        }

        lock (l)
        {
            // double lock check
            if (!isClientRegistered)
            {
                return;
            }

            //webServiceClient.UnegisterClient(clientHandle);
        }
    }
    #endregion

    #region Phone extension methods
    public bool SubscribeToEventsForExtension(string extension)
    {
        if (monitoredExtensions.Contains(extension))
        {
            return false;
        }

        lock (monitoredExtensions.SyncRoot)
        {
            // double lock check
            if (monitoredExtensions.Contains(extension))
            {
                return false;
            }

            RegisterClientIfNeeded();

            // open line so we receive events for extension
            LineInfo lineInfo;
            try
            {
                //lineInfo = webServiceClient.OpenLine(clientHandle, extension);
            }
            catch (FaultException<PhoneSystemWebSDKErrorDetail>)
            {
                // TODO: log error
                return false;
            }

            // add extension to list of monitored extensions
            //monitoredExtensions.Add(extension, lineInfo.lineID);
            monitoredExtensions.Add(extension, 1);

            // start event poller thread if not already started
            if (eventWatcherThread.ThreadState == ThreadState.Stopped || eventWatcherThread.ThreadState == ThreadState.Unstarted)
            {
                eventWatcherThread.Start();
            }

            return true;
        }
    }

    public bool UnsubscribeFromEventsForExtension(string extension)
    {
        if (!monitoredExtensions.Contains(extension))
        {
            return false;
        }

        lock (monitoredExtensions.SyncRoot)
        {
            if (!monitoredExtensions.Contains(extension))
            {
                return false;
            }

            // close line
            try
            {
                //webServiceClient.CloseLine(clientHandle, (int) monitoredExtensions[extension]);
            }
            catch (FaultException<PhoneSystemWebSDKErrorDetail>)
            {
                // TODO: log error
                return false;
            }

            // remove extension from list of monitored extensions
            monitoredExtensions.Remove(extension);

            // if we are not monitoring anything else, stop the poller and unregister the client
            if (monitoredExtensions.Count == 0)
            {
                eventWatcherThread.Abort();
                UnregisterClient();
            }

            return true;
        }
    }

    public bool IsExtensionMonitored(string extension)
    {
        lock (monitoredExtensions.SyncRoot)
        {
            return monitoredExtensions.Contains(extension);
        }
    }
    #endregion

    #region Dispose
    public void Dispose()
    {
        lock (l)
        {
            // close any open lines
            var extensions = monitoredExtensions.Keys.Cast<string>().ToList();

            while (extensions.Count > 0)
            {
                UnsubscribeFromEventsForExtension(extensions[0]);
                extensions.RemoveAt(0);
            }

            if (!isClientRegistered)
            {
                return;
            }

            // unregister web service client
            UnregisterClient();
        }
    }
    #endregion
}
+2  A: 

No.

Threads that you create using new Thread(...) (As opposed to ThreadPool.QueueUserWorkItem) have nothing to do with the ThreadPool, regardless of IsBackground.

SLaks