c# – 如何在通过ChannelFactory创建的WCF服务上设置回调通道?
发布时间:2020-12-15 21:00:13 所属栏目:百科 来源:网络整理
导读:我需要我的WCF服务来向客户端发送事件.我已经读过这是通过回调通道发生的,我已经按照以下方式实现了它: 服务接口: public interface IServiceCallback{ [OperationContract(IsOneWay = true)] void OnNewAlert(Alert a); [OperationContract(IsOneWay = tr
我需要我的WCF服务来向客户端发送事件.我已经读过这是通过回调通道发生的,我已经按照以下方式实现了它:
服务接口: public interface IServiceCallback { [OperationContract(IsOneWay = true)] void OnNewAlert(Alert a); [OperationContract(IsOneWay = true)] void OnProductEdited(Product p); [OperationContract(IsOneWay = true)] void OnHighlightChanged(Dictionary<User,List<Product>> highlighted); [OperationContract(IsOneWay = true)] void OnCatalogUpdated(); event EventHandler NewAlert; event EventHandler ProductEdited; event EventHandler HighlightChanged; event EventHandler CatalogUpdated; } [ServiceContract(CallbackContract = typeof(IServiceCallback))] public interface IService : IDisposable { [OperationContract] List<Product> GetProducts(Predicate<Product> match = null,int limit = 0,string username = null); [OperationContract] Product GetProduct(Predicate<Product> match,string username = null); [OperationContract] Product GetRandomProduct(Predicate<Product> match = null,string username = null); [OperationContract] int GetFlagIndex(string flagName); [OperationContract] void SetFlag(string pid,string flagName,bool value); [OperationContract] List<Alert> GetAlerts(string username); [OperationContract] void DismissAlert(Alert alert,String username); [OperationContract] void HighlightProduct(List<string> pids,string user); [OperationContract] void EditProduct(string pid,Dictionary<string,object> fieldValues,string username = null); [OperationContract] void AttachModule(IModule m); [OperationContract] void Ping(); event EventHandler NewAlert; event EventHandler ProductEdited; event EventHandler HighlightChanged; event EventHandler CatalogUpdated; } 服务实施: namespace Service { [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall,ConcurrencyMode = ConcurrencyMode.Reentrant)] public class ServiceInstance : IService { List<IServiceCallback> callbackChannels = new List<IServiceCallback>(); //other vars public ServiceInstance() { //lots of stuff here } private User SignalUser(string username) { if (username == null) return null; IServiceCallback channel = OperationContext.Current.GetCallbackChannel<IServiceCallback>(); if (!callbackChannels.Contains(channel)) //if CallbackChannels not contain current one. { callbackChannels.Add(channel); } User user = knownUsers.Find(p => p.username == username); if (user == null) { user = new User(); user.username = username; user.highlighColor = Color.FromArgb(r.Next(0,128),r.Next(0,128)); knownUsers.Add(user); foreach (KeyValuePair<Alert,List<User>> kvp in alerts) { kvp.Value.Add(user); } } user.lastOnline = DateTime.Now; if(!onlineUsers.Contains(user)) onlineUsers.Add(user); return user; } //lots of other things here } } 客户端的回调实现: class ServiceEventHandler : IServiceCallback { public event EventHandler NewAlert; public event EventHandler ProductEdited; public event EventHandler HighlightChanged; public event EventHandler CatalogUpdated; public void OnCatalogUpdated() { CatalogUpdated?.BeginInvoke(null,null,null); } public void OnHighlightChanged(Dictionary<User,List<Product>> highlighted) { HighlightChanged?.BeginInvoke(highlighted,EventArgs.Empty,null); } public void OnNewAlert(Alert a) { NewAlert?.BeginInvoke(a,null); } public void OnProductEdited(Product p) { ProductEdited?.BeginInvoke(p,null); } } 但这是我的问题: EventHandler eventHandler = new EventHandler(); MyServiceClient client = new MyServiceClient(new InstanceContext(eventHandler)); 根据StackOverflow的回答: 但我没有像这样连接到我的服务,因为我的客户端不知道服务的实现,它只知道这两个接口! public static IService GetService(string serviceAddress) { Uri service_uri = new Uri(serviceAddress); var endpoint = new EndpointAddress(service_uri,new[] { AddressHeader.CreateAddressHeader(settings["username"],"","") }); IService service = ChannelFactory<IService>.CreateChannel(new BasicHttpBinding(),endpoint); return service; } 那么如何让回调起作用呢? 更新: 好吧,正如评论所提出的,我用DuplexChannelFactory替换了ChannelFactory,用WsDualHTTPBinding替换了BasicHTTPBinding,我没有得到服务器的响应.如果我刮开回调处理程序,我会得到BasicHTTPBinding的响应.基本上: [ServiceContract] BasicHttpBinding(); ChannelFactory<IService>.CreateChannel(binding,endpoint); ^这有效 [ServiceContract(CallbackContract = typeof(IServiceCallback))] WSDualHttpBinding(WSDualHttpSecurityMode.None); DuplexChannelFactory<IService>.CreateChannel(new InstanceContext(handler),binding,endpoint); ^这不. 它适用于localhost,但不适用于LAN或Internet.服务器和客户端都禁用防火墙.当我尝试联系服务器时,我得到60秒超时. 解决方法
我发现我的连接问题是由于在客户端的路径上没有设置端口转发.由于我无法确保对客户端进行正确的端口访问,因此我已恢复为非回调模型,并将使用来自客户端的常规请求从服务接收累积的事件数据.可能效率不高,但到目前为止似乎是一种万无一失的方法.谢谢大家的关注.
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |