zoukankan      html  css  js  c++  java
  • 自定义Unity基于PerCall的生存期模型

    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();
        }

  • 相关阅读:
    Matlab高级教程_第一篇:Matlab基础知识提炼_01
    量化投资_量化投资系统框架的DIY_02_01
    计量经济与时间序列_时间序列之物理含义
    计量经济与时间序列_协整和误差修正模型
    数学之美_正态分布(Python代码)
    [转载] ./configure,make,make install的作用
    [转载]Deep Learning(深度学习)学习笔记整理
    AJAX XML 实例
    百度搜索插件源码
    apache 服务器在ubuntu上图片无法显示解决
  • 原文地址:https://www.cnblogs.com/gaochundong/p/unity_per_call_context_lifetime_manager.html
Copyright © 2011-2022 走看看