Search code examples
c#wcf

WCF Library with threads in a Windows Service


This is my first WCF Library and I created it within a Windows Service, which I can access just fine and process through it, but unlike a normal library, I can't seem to access any of it's method classes outside of the Web Interface. The WCF Library has some threading within it that stays up until it needs to shutdown and I need the ability to tell this library the service is shutting down and it needs to close out the threads within itself gracefully. I'm guess I'm missing something simple, but maybe I can capture the Close() being called from within the WCF Library?

ServiceHost oServiceHost = new ServiceHost(typeof(WCFListener.MyClass));
oServiceHost.Open();

//wait until shutdown is called.
while (!_shutDownEvent.WaitOne(Timeout.Infinite));

//HERE I NEED TO TELL THE LIBRARY TO STOP ANY THREADS OR 
//WITHIN THE WCF CAPTURE CLOSE() WAS CALLED.

if (oServiceHost != null)
{
    //close out the WCF Listener service.
    oServiceHost.Close();
    oServiceHost = null;
}

I know how to launch the WCF Library as it's working and processing, but there are threads that are created within the WCF Libray and stay OPEN in the WCF Library. I need the WCF Library to start closing threads property when Windows tells my Windows Service it needs to stop. serviceHost.Close() doesn't kill the threads that have been created nor do I want it to. This is causing the Windows service to freeze waiting for the threads to stop.. I'm trying to figure out how I can tell the WCF Library this as it doesn't have a interface like an object. I'm sure this is simple and I'm overthinking it.


Solution

  • It is a little hard to understand what your problem actually is, but generally, you would proceed as follows:

    Update I have assumed hypothetical MyLibraryClass.Initialize() and MyLibraryClass.Shutdown() methods, that your library provides, below.

    So, your library would provide something like this:

      public static class MyLibraryClass
      {
          public static void Initialize(ServiceHost serviceHost)
          {
            serviceHost.Closed += (...) {
               // Cleanup when host closes.
               Shutdown();
            }
          }
          public static void Shutdown()
          {
              // Cleanup. E.g. stop threads, etc.
          }
       }
    

    If that is not correct, you need to provide more source/context in your question about what you can do or can't do. In general, it is always a good idea to not have explicit active components in a library (like threads, etc.); if required to do so, than you should provide an "initialize" and/or "shutdown" method for the users of your library.

    public class MyService : ServiceBase
    {
        private ServiceHost serviceHost;
    
        protected override void OnStart(string[] args)
        {
          serviceHost = /* new, etc. */
    
          // Somehow pass the serviceHost reference to your library,
          // then subscribe to `Closed`, e.g.
    
    
          MyLibraryClass.Initialize(serviceHost);
    
          serviceHost.Open();
        }
    
        protected override void OnShutdown()
        {
          serviceHost.Close();
          // Do additional cleanup, e.g. stopping your "library threads"
          // Alternative to the event-approach in "OnStart", simply call
          MyLibraryClass.Shutdown();
        }
    }
    

    That is, you would open your host when the service starts, and close it when the service ends. There should be no reason to do any extra "waiting", etc. on a service shutdown.

    The Windows Service Control Manager will call (via P/Invoke, etc.) the OnStart and OnShutdown methods when it starts / stops the service. The important thing is, that you do your actual work in a background thread, i.e. exit the OnStart and OnShutdown methods as quick as possible - that is a trait that you get for free with ServiceHost in this case.