zoukankan      html  css  js  c++  java
  • 自定义Unity生存期模型PerCallContextLifeTimeManager

    自定义Unity生存期模型PerCallContextLifeTimeManager

    PerThreadLifetimeManager的问题

    使用Unity内置的PerThreadLifetimeManager生存期模型时,其基于ThreadStatic的TLS(Thread Local Storage)设计,也就是说对于每个托管的ManagedThreadId,其会缓存已生成的对象实例。

    由于CLR维护了托管线程池,使用过的线程并不会立即销毁,在需要的时候会继续复用。在类似ASP.NET PerCall或WCF PerCall条件下,当Call1在线程ManagedThreadId1中处理完毕后,Call2发生,而Call2很有可能也在线程ManagedThreadId1中处理。这种条件下Call2会自动复用处理Call1时生成并缓存的对象实例。

    如果我们希望每次调用(PerCall)都生成专用的对象实例,则PerThreadLifetimeManager在此种场景下不适合。

    解决办法有两种:

    1. 继续使用PerThreadLifetimeManager模型,不适用ThreadPool,而手动创建和销毁线程。
    2. 自定义对象生存期模型

    PerCallContextLifeTimeManager

    复制代码
        public class PerCallContextLifeTimeManager : LifetimeManager
        {
          private string _key = 
            string.Format(CultureInfo.InvariantCulture, 
            "PerCallContextLifeTimeManager_{0}", Guid.NewGuid());
    
          public override object GetValue()
          {
            return CallContext.GetData(_key);
          }
    
          public override void SetValue(object newValue)
          {
            CallContext.SetData(_key, newValue);
          }
    
          public override void RemoveValue()
          {
            CallContext.FreeNamedDataSlot(_key);
          }
        }
    复制代码

    使用举例

    复制代码
        private static void TestPerCallContextLifeTimeManager()
        {
          IExample example;
          using (IUnityContainer container = new UnityContainer())
          {
            container.RegisterType(typeof(IExample), typeof(Example),
              new PerCallContextLifeTimeManager());
    
            container.Resolve<IExample>().SayHello();
            container.Resolve<IExample>().SayHello();
    
            Action<int> action = delegate(int sleep)
            {
              container.Resolve<IExample>().SayHello();
              Thread.Sleep(sleep);
              container.Resolve<IExample>().SayHello();
            };
    
            Thread thread1 = new Thread((a) => action.Invoke((int)a));
            Thread thread2 = new Thread((a) => action.Invoke((int)a));
            thread1.Start(50);
            thread2.Start(55);
            thread1.Join();
            thread2.Join();
    
            ThreadPool.QueueUserWorkItem((a) => action.Invoke((int)a), 50);
            ThreadPool.QueueUserWorkItem((a) => action.Invoke((int)a), 55);
            Thread.Sleep(100);
    
            ThreadPool.QueueUserWorkItem((a) => action.Invoke((int)a), 50);
            ThreadPool.QueueUserWorkItem((a) => action.Invoke((int)a), 55);
            Thread.Sleep(100);
    
            ThreadPool.QueueUserWorkItem((a) => action.Invoke((int)a), 50);
            ThreadPool.QueueUserWorkItem((a) => action.Invoke((int)a), 55);
            Thread.Sleep(100);
    
            example = container.Resolve<IExample>();
          }
    
          example.SayHello();
    
          Console.ReadKey();
        }
    复制代码

     
     
     
    标签: C#.NETWCFIoCDIUnity
  • 相关阅读:
    如何禁止在DBGRID末位自动添加一行记录
    DELPHI加密字串(异或运算加密)
    SQL SERVER 正则替换
    sql里的正则表达式
    UFIDA
    delphi raise 语句: 抛出异常
    delphi怎么一次性动态删除(释放)数个动态创建的组件?
    Delphi动态创建组件,并释放内存
    DELPHI 动态 创建和释放 多个 EDIT 控件
    禁止在DBGrid中按delete删除记录
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3021163.html
Copyright © 2011-2022 走看看