每次调用端点时,自托管 WCF 服务全局对象似乎都是新创建的

Posted

技术标签:

【中文标题】每次调用端点时,自托管 WCF 服务全局对象似乎都是新创建的【英文标题】:Self hosted WCF service global object appears to be newly created every time an endpoint is invoked 【发布时间】:2019-06-15 00:09:32 【问题描述】:

按照教程here 我在 Windows 服务中自行托管 WCF 服务。我的 WCF 服务包含一个我定期更新的全局对象。我想将该对象序列化为 JSON 并通过服务端点返回该 JSON 字符串。当我访问在服务上调用 serialize 方法的端点时,我得到了似乎是全局的全新实例。服务设置为[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]

我正在用和教程一样的方式实例化:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class MyWindowsService: ServiceBase
public ServiceHost serviceHost = null;

    public Service()
    
        ServiceName = "MyService";
    

    public static void Main()
    
        ServiceBase.Run(new MyWindowsService());
    

    protected override void OnStart(string[] args)
    
        if (serviceHost != null)
        
            serviceHost.Close();
        

        serviceHost = new ServiceHost(typeof(MyWCFService));
        serviceHost.Open();
    

    protected override void OnStop()
    
        if (serviceHost != null)
        
            serviceHost.Close();
            serviceHost = null;
        
    

我的 WCF 服务如下所示:

public class MyWCFService: IWCFService

    private myObject = mySerializableObject;

    public MyWCFService()
    
        myObject = new MySerializableObject();
        myObject.Init();
    

    public Stream GetJSON()
    
        MemoryStream stream = new MemoryStream();
        DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(MySerializableObject));

        ser.WriteObject(stream, myObject);

        string jsonString = Encoding.ASCII.GetString(stream.ToArray());


        byte[] resultBytes = Encoding.UTF8.GetBytes(jsonString);
        WebOperationContext.Current.OutgoingResponse.ContentType = "text/plain";
        return new MemoryStream(resultBytes);
    

如果我GET GetJSON 端点,返回的字符串是对象的全新初始化。如果我中断 GetJSON 方法,myObject 会显示所有新初始化的值。在 MySerializableObject 更新代码中放置断点表明更新正确发生并保存到内存中的对象中。

在普通的控制台应用程序中运行相同的代码可以正常工作。为什么会出现差异?我是否错误地处理了全局?

【问题讨论】:

从控制台应用程序中,您是否正在启动服务?通常,服务会在机器启动时自动启动。所以我不确定为什么需要在c#应用程序中启动服务。 我正在使用控制台应用程序独立调试非服务代码。该服务当前设置为手动启动。 尝试使用嗅探器并将控制台应用程序与 c# 应用程序进行比较。检查 http 标头以查看它们是否相同。一种怀疑是控制台正在使用 cookie,而 c# 没有使用 cookie。 【参考方案1】:

想通了...我遇到了几个问题。

    如here 所示,我的 InstanceContextMode 声明 没有装饰正确的服务,所以它仍在运行 默认的每次调用上下文 - 因此,每个连接上都有一个新的状态对象。 O'Reilly 告诉我我没有创建我的单身人士 实例正确。旁注,当使用实例创建 ServiceHost 时,您可以在构造函数或 App.config 中显式指定基本 URI。这让我有些困惑,因为我遇到的许多示例都是在构造函数而不是配置中传递的。

这是我的后代工作实现:

[ServiceContract(Namespace = "http://my.super.original.namespace")]
public interface IWCFService

    [OperationContract, WebGet]
    Stream GetJSON();


//Decorator goes on WCF service, not the Windows service
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class MyWCFService : IWCFService

    private StateObject _myStateObject;

    public MyWCFService()
    
        _myStateObject = new StateObject();
        _myStateObject.Init();
    

    public Stream GetJSON()
    
        .
        .
        .
        return "JSON String Here";
    


public class MyWindowsService : ServiceBase

    public ServiceHost serviceHost = null;
    private readonly MyWcfService _wcfSingleton;

    public MyWindowsService()
    
        ServiceName = "WindowsServiceNameHere";
        _wcfSingleton = new MyWCFService();
    

    public static void Main()
    
        ServiceBase.Run(new MyWindowsService());
    

    // Start the Windows service.
    protected override void OnStart(string[] args)
    
        if (serviceHost != null)
        
            serviceHost.Close();
        

        //load WCF Singleton Instance and open it for connections
        serviceHost = new ServiceHost(_wcfSingleton);
        serviceHost.Open();
    

    protected override void OnStop()
    
        if (serviceHost != null)
        
            serviceHost.Close();
            serviceHost = null;
        
    

【讨论】:

以上是关于每次调用端点时,自托管 WCF 服务全局对象似乎都是新创建的的主要内容,如果未能解决你的问题,请参考以下文章

WCF 服务端点与主机基地址

如何为自托管 WCF 服务启用跨域调用

WCF Net.tcp 仅在本地失败

具有相对路径的 Asp.net 自托管 WCF 服务 WSDL

MemoryCache 和多个每次调用 WCF 服务

WCF 和返回的对象名称