代码之家  ›  专栏  ›  技术社区  ›  mafu

在失败时正确删除WCF回调的模式

  •  1
  • mafu  · 技术社区  · 15 年前

    我有一个存储连接实例静态列表的类。在回调时,会调用列表中的每个实例,如果调用失败,则会从列表中删除该实例。

    class Foo : IDisposable
    {
        private static readonly List<Foo> _Connections = new List<Foo> ();
        private readonly IFooCallback CallbackChannel;
    
        internal Foo ()
        {
            CallbackChannel = OperationContext.Current.GetCallbackChannel<IFooCallback> ();
    
            lock (_Connections) {
                _Connections.Add (this);
                OperationContext.Current.Channel.Closing += (s, e) => Dispose ();
                OperationContext.Current.Channel.Faulted += (s, e) => Dispose ();
            }
        }
    
        public void Dispose ()
        {
            lock (_Connections) {
                _Connections.Remove (this);
            }
        }
    
        private void RaiseCallback ()
        {
            List<Foo> connections;
            lock (_Connections) {
                connections = new List<Foo> (_Connections);
            }
            foreach (var con in connections) {
                try {
                    con.CallbackChannel.SomeCallback ();
                }
                catch (CommunicationException) {
                    OperationContext.Current.Channel.Abort ();
                }
                catch (TimeoutException) {
                    OperationContext.Current.Channel.Abort ();
                }
            }
        }
    }
    

    我的想法:

    1. 实例的静态列表,每个实例存储CB通道。
    2. 在回调时,将创建(同步)和枚举(不同步)列表的副本。

    失败的回调会导致通道中止,进而导致从列表中释放和删除。这可能发生,也可能不发生在同一个线程上(无法保证,因为由于不同的事件,释放可能随时引发)。

    我的问题是,这是处理实例存储和回调错误处理的常见模式,还是如何改进它?在用RaiseCallback枚举之前复制列表是一个错误还是正确的?

    0 回复  |  直到 15 年前