Wednesday, August 4, 2010

Self Hosting in WCF

Self Hosting in WCF can pose some small issues when you would like to host many services in one service.  Here's some template code I have used before to solve this:

Code Download

Why host in a Console?  Usually the intention is to host inside another application or a Windows service, and testing it inside a console a simplier than the real application.  Why not IIS/WAS? If  you need to run long lived background threads hosting in IIS or WAS will have issues.

The main idea is to safely host each service inside a using block and use a controlling thread to signal hosting threads to trigger shut-down.

First I put all metadata for a service into an array of container classes. Then I can loop through and intitialise them, then wait for them all to come online.



           var services = new[]
                               {
                                   new SingleServiceHostContainer(typeof(TestService1), testMode) { Fake = typeof(TestService1Fake) }, 
                                   new SingleServiceHostContainer(typeof(TestService2), testMode) { Fake = typeof(TestService2Fake) }
                               };

            // Have used Threads instead of the task factory to ensure they start
            var hostThreads = new List<Thread>();
            Array.ForEach(
                services, 
                s =>
                    {
                        s.ReadyToExitResetEvent = ReadyToExitResetEvent;
                        var thread = new Thread(s.Run);
                        hostThreads.Add(thread);
                        thread.Start();
                    });

            // Wait for initialisation to complete
            WaitHandle.WaitAll(services.Select(s => s.InitializationComplete).ToArray());
            Array.ForEach(services, s => s.WriteOutputToConsole());

            Console.ForegroundColor = ConsoleColor.Gray;
            Console.WriteLine("Press any key to quit");
            Console.ReadKey();

            ReadyToExitResetEvent.Set();
            hostThreads.ForEach(t => t.Join());


Once they are all signalling they have completed their initialisation, then the main thread can simply wait until the user is ready to close the console and thereby shut down all the services.

There's a little noise in the code download, for things like dependency injection and WCF Data Services (OData services).

No comments:

Post a Comment