使用InstanceContextMode.Single

时间:2015-09-13 22:13:03

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

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

  1. WCF服务,我在C#控制台应用程序中自我托管。当WCF客户端同意他们调用Login函数时,我(尝试!)通过GetCallbackChannel存储他们的回调
  2. 第三方DLL通过与库不同的线程上的委托调用我的控制台
  3. 在这个控制台回调中,我然后调用WCF服务,该服务池然后被传递给WCF服务,然后WCF服务通过回调合同广播到所有连接的客户端。
  4. 一切正常,客户端连接,调用Login,我保存回调接口对象。

    然而,当我从我的服务访问代码时,我发现它是一个全新的对象而我的_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方法进入对象时虽然对象似乎是新的(成员是空的)但构造函数断点没有被击中 - 怎么会这样?

2 个答案:

答案 0 :(得分:1)

我已经在我控制的静态全局成员变量后面托管了第三方应用程序。所以我负责第三方lib和普通wcf调用之间的所有通信,状态和清理。我负责第三方应用程序的线程生命周期。如果我创建它们,我必须关闭它们。在我自己的名单中保留参考文献。

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

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

这使得wcf部分成为普通的线程(线程池)概念,没有特殊的声明。

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

service.Notify( “HI”)    到Console.ReadLine();

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

答案 1 :(得分:0)

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

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

我通过右键单击WCF Project - &gt;禁用了为WCF .svc服务启动的WCF服务主机Properties - &gt; WCF Options - &gt;未经批准的Start WCF Service Host when debugging another project in the same solution