0

So I have an object that raises events and a WCF Service hosted within a windows service.

The raised events are currently in a class within the Windows service and the WCF Service subscribes to those events and when the events fire they are meant to be a callback to the client to let the client know something happened on another part of the Windows Service.

The issues is that at times the callbacks work and at times they do not. I have checks to see if there are any clients to call back to if not I don't bother. I am not sure the best way to implement this is because at times the:

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

Gets a callback at other times it exceptions out or is set to null because the event coming into the WCF service is coming from another part of the Windows Service (A class) rather than from the OperationContext.

In Short How can I setup my WCF service to alert clients when events occurred in another part of my windows service?

(More Code)

Before publishing out the events I do a check like so (Only care to publish when we have clients):

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

Then I publish it all out like so:

            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);
4

1 に答える 1

0

したがって、コールバックを取得し、 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);
            }
        }
    }

次に、publish メソッドで、現在のコールバック チャネルに設定しようとして簡単なチェックを行っていますが、それが失敗した場合は、そこにあることがわかっているものを取得してください。

        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];
            }
        }

これは機能しますが、これがこれを行うための最良の方法であるかどうかはわかりません。

于 2013-08-23T17:35:04.070 に答える