【问题标题】:State inside self-hosted WCF service being lost with InstanceContextMode.Single自托管 WCF 服务内部的状态因 InstanceContextMode.Single 而丢失
【发布时间】:2015-12-09 21:06:49
【问题描述】:

我正在使用 WCF 服务并自行托管它,因为并非所有内容都包含在服务本身中(一些外部事件发生在服务之外):

  1. WCF 服务,我在 C# 控制台应用程序中自行托管它。当 WCF 客户端连接时,他们调用 Login 函数,我(尝试!)通过 GetCallbackChannel 存储他们的回调
  2. 第 3 方 DLL,它通过与库不同线程上的委托调用我的控制台
  3. 在此控制台回调中,我随后调用 WCF 服务池,然后将其传递给 WCF 服务,然后 WCF 服务通过回调合约向所有连接的客户端广播。

客户端连接,调用登录,我保存回调接口对象,一切都很好。

但是,当我从我的服务访问代码时,我发现它是一个全新的对象并且我的 _endPointMap 是空的(尽管我将它存储在客户端调用的 Login 方法中):

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class Service : IService, IEndpointNotifier
{
    public readonly TwoWayDictionary<string, IClientCallback> _endpointMap = new TwoWayDictionary<string, IClientCallback>();

    // called by WCF client when they click the login button - it works
    public void Login(string username)
    {
        var callback = OperationContext
            .Current
            .GetCallbackChannel<IClientCallback>();

        _endpointMap.AddOrUpdate(username, callback);
        list.Add(username);
    }

    // called by the WCF self-host console app
    public void IEndpointNotifier.Notify(string info, string username)
    {
        // at this point my list _endpointMap is empty despite
        // having received a Login previously and adding to the
        // list. so i am unable to call my clients back!!

        _endPointMap.Count(); // is 0 at this point?!!
    }
}

我的主控制台应用程序也可以正常启动服务,如下所示:

static void Main(string[] args)
{
    var service = new Service();
    var host = new ServiceHost(service);

    // between the above line and the task below calling
    // service.Notify I click a number of times on client
    // which calls the Login method

    Task.Run(() =>
    {
        for (var i = 0; i < 3; i++)
        {
            Thread.Sleep(10000);

            // at this point, service seems like a new object?!
            // any data saved in the list member will be lost,
            // and will only see the single entry from time of
            // construction

            service.Notify("hi","bob");
        }
    });

    Console.ReadLine();
}

请提问

  1. 该对象似乎与之前操作中修改的对象完全不同(从客户端登录时) - 有没有办法告诉我实际查看的是什么服务对象(相当于旧的 C++ 时代和查看this) 的地址指针?

  2. 单例属性似乎被忽略了[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]任何想法我做错了什么(为什么内部列表变量不断重置)?

  3. WCF 服务不能是自包含的。如何根据最佳实践实现 WCF 自托管应用程序和 WCF 服务之间的通信,或者这是否滥用 WCF 以及设计用途(在考虑范围等时)?

  4. 我在构造函数中设置了一些虚拟值的断点。该断点仅在我构造它时第一次被击中。当我通过 service.Notify 方法进入对象时,虽然对象看起来是新的(成员为空),但没有命中构造函数断点 - 怎么回事?

【问题讨论】:

    标签: c# .net multithreading wcf self-hosting


    【解决方案1】:

    我在我控制的静态全局成员变量后面托管了第 3 方应用程序。所以我负责 3rd 方库和正常 wcf 调用之间的所有通信、状态和清理。我负责第 3 方应用程序的线程生命周期。如果我创建它们,我必须关闭它们。在我自己的列表中保存引用。

    就像它是一个单独的应用程序,但它们恰好位于同一个进程空间中。与第 3 方应用程序之间的所有通信均由我正式控制。

    您可能需要一个线程在使用后查找已完成或已放弃的第 3 方对象,以便在正常的 wcf msg 处理之外自行杀死它们。

    这让 wcf 部分成为一个没有特殊声明的普通线程(线程池)概念。

    旁注: 我会取出循环并在您的简单模型中使其成为两行。

    service.Notify("hi") Console.ReadLine();

    这将公开您的对象生命周期详细信息,而不是将它们隐藏 3 秒。

    【讨论】:

      【解决方案2】:

      我发现为什么没有保存这些值...我的 WCF 客户端代理连接到 VS WCF 服务主机,而不是代码中的主机!

      当我看到 WCF 服务主机在服务栏托盘中运行时,我注意到了这一点。

      我通过右键单击 WCF Project -> Properties -> WCF Options -> 取消选中 Start WCF Service Host when debugging another project in the same solution 来禁用 WCF 服务主机启动 WCF .svc 服务

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-08-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-07
        • 1970-01-01
        相关资源
        最近更新 更多