我正在尝试让WCF服务在InstanceContextMode.Single中运行,这样所有请求都可以共享相同的服务状态。但是,当我尝试使用此行为启动服务时,我仍然可以看到服务的构造函数随每个请求被调用。我无法找到更新ServiceBehaviorAttribute的快速方法,这就是为什么我要替换它(InstanceContextMode的默认值不是Single)。好像我们启动它时有一个实例,然后是稍后进入的所有请求的另一个实例。什么想法可能会出错?
/// <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();
}
通常,您将ServiceBehaviorAttribute
设置为实现服务的类的真实属性。我不是C ++ / CLI专家,但我猜你自己将CAutomation::typeid
传递给ServiceHost
构造函数,然后CAutomation
就是你的服务类。那是对的吗?
如果是这样,那么它应该足以在ServiceBehaviorAttribute
类上设置CAutomation
。
Igor Labutin向我指出了正确的方向,但这里真正的问题是服务宿主对象的创建将创建一个类的实例,其类型被传递给它的构造函数,至少在[ServiceBehaviorAttribute(InstanceContextMode = InstanceContextMode::Single)]
中。基本上,ServiceHost对象不应该是CAutomation类构造函数。我将该对象移出该构造函数之外的另一个对象,该对象负责服务何时启动并纠正了该问题。我将粘贴一些代码示例,这有助于说明更好的方法。
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;
}
}
}
}