简体   繁体   English

如何从WCF C#的托管过程中调用ServiceHost的方法

[英]How to call a method of the ServiceHost from the hosting process in WCF C#

I have a publisher / subscriber pattern WCF Duplex ServiceHost that is hosted by a Windows Service. 我有Windows服务托管的发布者/订阅者模式WCF双工ServiceHost。 The Windows Service receives events from a separate process. Windows服务从单独的进程接收事件。 OnEvent I would like to force my WCF Host to publish that data to all subscribed clients. OnEvent我想强制WCF主机将该数据发布到所有订阅的客户端。 Typically if a Client is calling this is straight forward. 通常,如果客户正在呼叫,这很简单。 But when my Service Host needs to do this - I can't get my head around HOW to do that. 但是,当我的服务主机需要执行此操作时-我无法理解如何执行此操作。 I have 2 questions: 我有两个问题:

1: I do not know how to create a Channel in WCFHost from my Windows Service so that it can use to publish to the Subscribers. 1:我不知道如何从Windows服务在WCFHost中创建频道,以便可以将其用于发布到订阅服务器。

2: I read Creating WCF ChannelFactory so I do know I am creating a DuplexChannelFactory (2 per second ) which might be too much overhead. 2:我阅读了创建WCF ChannelFactory,所以我知道我正在创建DuplexChannelFactory(每秒2个),这可能会导致过多的开销。

Any help examples, hints are greatly appreciated. 任何帮助示例,提示都将不胜感激。 I am not a WCF expert and currently know more about it than I thought I should have to know in order to use it. 我不是WCF专家,并且目前比我想了解的要了解更多信息。

I had read on SO Can I call a Method in a self hosted wcf host locally? 我已经阅读过SO 可以在本地自托管的wcf主机中调用方法吗?

So then I have created a method inside my WCFHost like so: 因此,我在WCFHost中创建了一个方法,如下所示:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession,
                 AutomaticSessionShutdown = false,
                 IncludeExceptionDetailInFaults = true)]
[CallbackBehavior(UseSynchronizationContext = false, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class ServerHost<TService> : ServiceHost where TService : class
{     
   public T GetDuplexClientChannel<T, Cback>(BindingType bindingType, EndpointAddress endPointAddress)  where T : class 
    {
        ServiceEndpoint sep = GetContractServiceEndPoint<T>(bindingType, endPointAddress);
        lock (_syncRoot)
        {
            DuplexChannelFactory<T> factory = new DuplexChannelFactory<T>(typeof(Cback), sep);
            return factory.CreateChannel(endPointAddress);
        }
    }    
}

I get an error of course that there is no InstanceContext because I am constructing using typeof(Cback) .. 我当然会得到一个错误,即没有InstanceContext,因为我正在使用typeof(Cback)进行构造。

"This CreateChannel overload cannot be called on this instance of DuplexChannelFactory, as the DuplexChannelFactory was initialized with a Type and no valid InstanceContext was provided." “不能在此DuplexChannelFactory实例上调用此CreateChannel重载,因为DuplexChannelFactory已使用类型初始化,并且未提供有效的InstanceContext。”

So I am not sure how I can go about performing this ? 因此,我不确定如何执行此操作? And for those that say read the error : yes I read the error. 对于那些说读取错误的人:是的,我读取了错误。 Now how to do that with an InstanceContext that does not exist as OperationContext.Current does not exist at this point as I am calling this method form my Hosting Process into my WCFHost. 现在如何使用不作为OperationContext.Current存在的InstanceContext来执行此操作,因为我正在从WingHost的Hosting Process中调用此方法,因此目前不存在。

So if I could have a nice example of how to do this - even if I must use the code example on the 2nd link (of course implementing the DuplexChannelFactory) I would greatly appreciate it. 因此,如果我有一个很好的示例,即使必须在第二个链接上使用代码示例(当然要实现DuplexChannelFactory),我也将不胜感激。

EDIT Basically the windows Service is doing some heavy work monitoring other services, about 2 times a second it then must publish that to "Subscribed" Clients via WCF. 编辑基本上,windows服务正在做一些繁重的工作来监视其他服务,大约每秒2次,然后必须通过WCF将其发布给“已订阅”客户端。

I think you have got very confused about how everything is wired together and are mixing concepts from the client in with the service. 我认为您对所有内容如何连接在一起以及将来自客户端的概念与服务混为一谈感到非常困惑。 You haven't provided much concrete information about your scenario to go on so I'm going to provide a small example and hopefully you will be able to apply the ideas to your problem. 您没有提供有关您的情况的详细信息,因此我将提供一个小例子,希望您能够将这些想法应用于您的问题。

[ServiceContract(CallbackContract=typeof(IMyServiceCallback))]
public interface IMyService
{
    [OperationContract]
    void Register();
}

public interface IMyServiceCallback
{
    [OperationContract]
    void ReceiveData(string data);
}

[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class MyService : IMyService
{
    static HashSet<IMyServiceCallback> s_allClients = new HashSet<IMyServiceCallback>();
    static object s_lockobj = new object();

    public void Register()
    {
        lock(s_lockobj)
        {
            _allClients.Add(OperationContext.Current.GetCallbackChannel<IMyServiceCallback>());
        }
    }

    public static void SendDataToClients(string data)
    {
        HashSet<IMyServiceCallback> tempSet;
        lock(s_lockobj)
        {
            tempSet = new HashSet<IMyServiceCallback>(_allClients);
        }
        foreach(IMyServiceCallback cb in tempSet)
        {
            try
            {
                cb.ReceiveData(data);
            }
            catch(Exception)
            {
                lock(s_lockobj)
                {
                    _allClients.Remove(cb);
                    cb.Abort();
                    cb.Dispose();
                }
            }
        }
    }
}

In your OnEvent method, you would call something similar to this inside your event method. 在您的OnEvent方法中,您将在事件方法中调用与此类似的内容。

MyService.SendDataToClients(mydata);

This uses static data to store the list of clients. 这使用静态数据来存储客户端列表。 If you wanted to do something like segment your clients for different endpoints, you would need to do something different. 如果您想做一些事情,例如将客户细分为不同的端点,则需要做一些不同的事情。 There is a potential out of order message and scaling problem with this code if your OnEvent method can be called again while the previous call hasn't completed. 如果在上一次调用尚未完成的情况下可以再次调用OnEvent方法,则此代码可能会出现乱序消息和扩展问题。 For example, if you receive 2 messages, the first being large and the second being small, you could potentially send the second smaller message to clients later in the HashSet iteration order before they have been sent the first message. 例如,如果您收到2条消息,第一条消息较大,第二条消息较小,则有可能在以后的HashSet迭代顺序中向客户端发送第二条较小的消息,然后再向它们发送第一条消息。 Also this won't scaled to a large number of clients as you could block timing out on one client holding up messages being sent to other clients. 而且,这不会扩展到大量客户端,因为您可能会阻止一个客户端暂停将邮件发送给其他客户端的超时。 You could use something similar to Task's to dispatch multiple message deliveries. 您可以使用类似于Task的方法来分派多个邮件传递。 If this needs to scale, I would suggest looking at Reactive Extensions for .Net 如果需要扩展,我建议您查看.Net的Reactive Extensions。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM