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
  • 相关阅读:
    MyEclipse 2015 Stable 2.0破解方法
    GeoGlobe Server运维
    GeoGlobe Server运维
    Silverlight用户无法注册之MySql.Data.dll不一致
    Photoshop影像匀色技术
    GeoGlobe Server使用问题收集
    Windows Server 2008 R2中无法使用360免费Wifi的解决方案
    吉奥平台软件安装经验分享
    U盘中毒后变为快捷方式的解决方法
    主机访问虚拟机中新建的网站
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3021163.html
Copyright © 2011-2022 走看看