【问题标题】:Simple cross-application data and event passing in C#C# 中简单的跨应用程序数据和事件传递
【发布时间】:2012-06-20 15:31:17
【问题描述】:

背景 我正在创建一个 ASP.net 应用程序,它使用自定义库(尚未公开发布,但很快)为 jQuery 中的 javascript 客户端提供长轮询处理程序。客户端将调用处理程序,等待处理程序返回一些数据,显示它,然后再次点击处理程序......清洗,冲洗,重复。

处理程序的工作是接受请求,将其放入一个集合(通常是List<>)并等待一个事件,其中包含要返回到等待请求的数据。我已经对此进行了测试,在我的服务器上的静态类中使用了一个简单的事件,这一切都很好。

问题 为了让所有客户端都能接收到消息,在我服务器上的所有 AppDomains 中,我创建了一个简单的 C# 控制台应用程序 - 它在后台运行并通过 WCF (NamedPipe) 提供 DataContract。然后,我在 ASP.net 中创建了一个客户端对象,它可以通过 WCF 接口与控制台应用程序对话。

我可以将消息同步拉入/推送到我的缓存中 - 这工作正常。但是,当我尝试在 WCF 合同上使用异步模式时,EndMethod 在我要求它之前被触发,直接在将 IAsyncResult 返回到 BeginMethod 之后。

我看不出有什么问题 - Google 有大量资源显示弱示例,但它们没有帮助。

我想要什么 无论如何,他们是否通过数据合同绑定到 WCF 上的事件?这样我就可以附加到事件并完成它。新消息进入缓存会触发我的事件,这会触发异步处理程序返回所有等待的请求。

这可能吗?如果可以,有人有任何示例/教程/示例吗?

要遵循的代码...

【问题讨论】:

    标签: c# wcf events asynchronous ipc


    【解决方案1】:

    我知道这是可能的,因为我已经这样做了,并且知道这方面的信息有限(我计划很快创建一篇博客文章)。基本上,您需要创建Subscribe/Unsubscribe WCF 方法,这将使您的端口保持打开状态。

    您的服务器代码应如下所示:

    [ServiceContract(SessionMode = SessionMode.Required,
        CallbackContract = typeof(IProcessorCallBack))]
    public interface IProcessor
    {
        [OperationContract]
        Boolean SubscribeToEvents();
    
        [OperationContract]
        Boolean UnsubscribeToEvents();
    }
    
    public interface IProcessorCallBack
    {
        [OperationContract(IsOneWay = true)]
        void OnEvent(EventArgs args);
    }
    
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
    public class DDSpeechMikeProcessor:IProcessor
    {
        private readonly List<IProcessorCallBack> _eventListeners = 
            new List<IProcessorCallBack>();
    
        public bool SubscribeToEvents()
        {
            var listenerToCallBacks =    
                OperationContext.Current.GetCallbackChannel<IProcessorCallBack>();
            if(!_eventListeners.Contains(listenerToCallBacks))
                _eventListeners.Add(listenerToCallBacks);
        }
    
        public bool UnsubscribeToEvents()
        {
            var listenerToCallBacks = 
                OperationContext.Current.GetCallbackChannel<IProcessorCallBack>();
            if (_eventListeners.Contains(listenerToCallBacks))
                _eventListeners.Remove(listenerToCallBacks);
        }
    
        //This is your server listening for the main event
        //which it will pass on to all listeners
        void OnEvent(EventArgs args)
        {
            foreach(var listener in _eventListeners)
            {
                try
                {
                    listener.OnEvent(args);
                }
                catch (Exception exception)
                {
                    RemoveListenerIfBadCommunication(listener, exception);
                }
            }
        }
    
        //If a listener did not unsubscribe before shutting down you will get exceptions
        private void RemoveListenerIfBadCommunication(IProcessorCallBack listener, 
            Exception exception)
        {
            if (exception.GetType() == typeof(CommunicationException)
                || exception.GetType() == typeof(CommunicationObjectAbortedException)
                || exception.GetType() == typeof(CommunicationObjectFaultedException)
            )
               _eventListeners.Remove(listener);
        }
    }
    

    在您的客户端代码中:

    public class Client : IProcessorCallBack
    {
        DuplexChannelFactory<IProcessor> _processorFactory;
        IProcessor _processor
        void OpenProcessor()
        {
            _speechMikeProcessorFactory = new DuplexChannelFactory<IProcessor>(
                  this,
                  new NetNamedPipeBinding(),
                  new EndpointAddress(baseUri + @"/" + HostName));
            _processor = _speechMikeProcessorFactory.CreateChannel();
            _processor.SubscribeToEvents();
        }
    
        void OnEvent(EventArgs args)
        {
             //Do Stuff
        }
    }
    

    如果我需要更详细的解释,请告诉我

    【讨论】:

    • 这种方法确实如我所愿。在我的情况下需要一些小的调整,但原则是可靠的。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-03
    • 2010-09-16
    相关资源
    最近更新 更多