由于对象未初始化(双工),WCF回调失败

本文关键字:WCF 回调 失败 双工 于对象 对象 初始化 | 更新日期: 2023-09-27 18:28:44

所以我有一个引发事件的对象和一个托管在windows服务中的WCF服务。

引发的事件当前在Windows服务中的一个类中,WCF服务订阅这些事件,当事件激发时,它们将作为客户端的回调,让客户端知道Windows服务的另一部分发生了什么。

问题是,有时回调有效,有时则无效。我要检查一下是否有客户可以回电,如果没有,我就不麻烦了。我不确定实现这一点的最佳方式是因为有时:

call = OperationContext.Current.GetCallbackChannel<IRiskEoDWCFEvents>();

在其他时候获取回调,该回调异常或设置为null,因为进入WCF服务的事件来自Windows服务(a类)的另一部分,而不是OperationContext。

简而言之如何设置WCF服务,以便在windows服务的另一部分发生事件时向客户端发出警报?

(更多代码)

在发布事件之前,我会做这样的检查(只有当我们有客户时才发布):

        private void Publish(EoDEvent eodListEvent, EoDItem item)
        {
            if ( _EoDEventSubscribers == null || _EoDEventSubscribers.Count == 0)
            {
               //Cannot publish because we have no one listening
               return;
            }
       .....

然后我就这样发布了:

            Thread myThread = new Thread(myObject =>
            {
                lock (_SubscriberLock)
                {
                    foreach (IRiskEoDWCFEvents callback in _EoDEventSubscribers)
                    {
                        if (callback.GetHashCode() != myObject.GetHashCode())
                        {
                            Logging.WriteLine("Sending event to {0}", callback.GetHashCode());
                            try
                            {
                               if (eodListEvent == EoDEvent.EoDComponentStarted)
                                    callback.EoDComponentStarted(item);
                               else if (eodListEvent == EoDEvent.EoDComponentCompleted)
                                    callback.EoDComponentCompleted(item);
                               .....
                            }
                            catch (Exception ex)
                            {
                                FaultException faultex = ex as FaultException;
                                if (faultex == null)
                                {
                                    Logging.WriteLine("Callback failed, removing {0}",                   callback.GetHashCode());
                                    toRemove.Add(callback);
                                }
                            }
                        }
                    }
                    if (toRemove.Count > 0)
                    {
                        foreach (IRiskEoDWCFEvents cb in toRemove)
                        {
                            _EoDEventSubscribers.Remove(cb);
                        }
                    }
                }
            });
            myThread.Priority = ThreadPriority.Highest;
            myThread.Start(call);

由于对象未初始化(双工),WCF回调失败

因此,我发现以下操作只是为了在foreach循环中获得回调并向客户端发送更新。

首先,我将呼叫设置为最新的用户

       public void Subscribe()
       {
         IRiskEoDWCFEvents callback = OperationContext.Current.GetCallbackChannel<IRiskEoDWCFEvents>();
         call = callback;
         lock (_SubscriberLock)
         {
             if (!_EoDEventSubscribers.Contains(callback))
             {
                 Logging.WriteLine("Adding callback {0}", callback.GetHashCode());
                 _EoDEventSubscribers.Add(callback);
            }
        }
    }

然后,在发布方法上,我正在进行快速检查,试图将其设置为当前回调通道,但如果失败,只需获取一个我知道存在的通道:

        if ( _EoDEventSubscribers == null || _EoDEventSubscribers.Count == 0)
        {
            //Cannot publish because we have no one listening
            return;
        }
        if (call == null)
        {
            try
            {
                call = OperationContext.Current.GetCallbackChannel<IRiskEoDWCFEvents>();
            }
            catch
            {
                call = _EoDEventSubscribers[0];
            }
        }

虽然这是有效的,但我不确定这是否是最好的方法