Search code examples
wcfc++-cli

Why isn't InstanceContextMode.Single working?


I'm trying to get the WCF service to run in InstanceContextMode.Single that way all requests can share the same state of the service. However, when I try to start the service with this behavior I can still see that the service's constructor gets called with each request. I couldn't figure out a quick way to update the ServiceBehaviorAttribute so that's why I'm replacing it (the default value for InstanceContextMode is not Single). Seems like there's one instance when we start it up and then another instance for all requests that come in later on. Any ideas what might be going wrong?

/// <summary>Constructor</summary>
CAutomation::CAutomation()
{
    //TODO:  pull from config
    m_Host = gcnew ServiceHost(CAutomation::typeid, gcnew Uri("http://localhost:8001/GettingStarted"));

    // add a service endpoint.
    m_Host->AddServiceEndpoint(IAutomation::typeid, gcnew WSHttpBinding(), "Automation");

    // add behavior
    ServiceMetadataBehavior^ smb = gcnew ServiceMetadataBehavior();
    smb->HttpGetEnabled = true;
    m_Host->Description->Behaviors->Add(smb);

    // enforce single instance behavior
    m_Host->Description->Behaviors->RemoveAt(0);
    ServiceBehaviorAttribute^ sba = gcnew ServiceBehaviorAttribute();
    sba->InstanceContextMode = InstanceContextMode::Single;
    m_Host->Description->Behaviors->Add(sba);
}

/// <summary>Starts the automation service.</summary>
void CAutomation::Start()
{
    m_Host->Open();
}

Solution

  • Igor Labutin pointed me in the right direction but the true issue here is that the creation of the service host object will create an instance of the class whose type is passed in to its constructor, at least when in [ServiceBehaviorAttribute(InstanceContextMode = InstanceContextMode::Single)]. Basically, the ServiceHost object should not have been the CAutomation class constructor. I moved that object outside of that constructor into another object which was responsible for when the service was supposed to start up and that corrected the issue. I'll paste a sample bit of code which helps to illustrate the better approach.

    class Program
    {
        static void Main(string[] args)
        {
            Uri address = new Uri
                ("http://localhost:8080/QuickReturns/Exchange");
            ServiceHost host = new ServiceHost(typeof(TradeService);
            host.Open();
            Console.WriteLine("Service started: Press Return to exit");
            Console.ReadLine();
         }
     } 
    
    [ServiceBehavior(InstanceContextMode=InstanceContextMode.Single,
        ReturnUnknownExceptionsAsFaults=true)]
    public class TradeService : ITradeService
    {
        private Hashtable tickers = new Hashtable();
        public Quote GetQuote(string ticker)
        {
            lock (tickers)
            {
                Quote quote = tickers[ticker] as Quote;
                if (quote == null)
                {
                    // Quote doesn't exist
                    throw new Exception(
                        string.Format("No quotes found for ticker '{0}'",
                        ticker)); 
                }
                return quote;
            }
        }
        public void PublishQuote(Quote quote)
        {
            lock (tickers)
            {
                Quote storedQuote = tickers[quote.Ticker] as Quote;
                if (storedQuote == null)
                {
                    tickers.Add(quote.Ticker, quote);
                }
                else
                {
                    tickers[quote.Ticker] = quote;
                }
            }
        }
    }