zoukankan      html  css  js  c++  java
  • HostingEnvironment RegisterObject和QueueBackgroundWorkItem

    其实网上关于HostingEnvironment 的RegisterObject和QueueBackgroundWorkItem文章已经很多了,典型是的

    QueueBackgroundWorkItem to reliably schedule and run background processes in ASP.NET

    Fire and Forget on ASP.NET   该文章里面涉及到一个开与项目 AspNetBackgroundTasks  

    而我本次的测试也是基于AspNetBackgroundTasks来测试的,Fire and Forget on ASP.NET里面提到了3点:个人英文不太好 就把原文贴出来吧

    大致意思就是Task.Run, Task.Factory.StartNew, Delegate.BeginInvoke, ThreadPool.QueueUserWorkItem 像这样的code, 在应用程程序域的DomainUnload以后,马上消失;在4.5.2 以后我们可以考虑 HostingEnvironment.QueueBackgroundWorkItem方法,它在 在应用程程序域的DomainUnload以后可以坚持30秒,后面我测试过也差不多就是这个时间。推荐做法就是用 HostingEnvironment.RegisterObject 它坚持的时间更长(我本地测试大致为5分钟)

    先看看 我的demo, 系统中总有一些比较耗时的操作, 通常我们可以采用分布式消息队列来实现,网上发现有人用 BlockingCollection<UserInfo>(new ConcurrentQueue<UserInfo>())来做简单的消息队列,那么我的担心就 出来了,BlockingCollection是线程安全的,但是它毕竟驻留在IIS进程里面,如果在release 跟新的时候,iis程序池会回收,BlockingCollection没有处理的数据是否会丢失

    先看看code吧,AsyncService每隔1秒就处理一条数据

    public class UserInfo
        {
            public string UserName { set; get; }
        }
        public class AsyncService
        {
           public static BlockingCollection<UserInfo> UerQueue;
            static AsyncService()
            {
                UerQueue = new BlockingCollection<UserInfo>(new ConcurrentQueue<UserInfo>());
            }
            public static void Start()
            {
                DateTime start = DateTime.Now;
                foreach (UserInfo item in UerQueue.GetConsumingEnumerable())
                {
                    ProcessUserInfo(item,(DateTime.Now-start).TotalSeconds);
                    Thread.Sleep(1000);
                }
            }
            private static void ProcessUserInfo(UserInfo userInfo,double seconds)
            {
                System.Diagnostics.Debug.WriteLine(userInfo.UserName+"------------"+seconds.ToString());
            }
        }

    在HomeController往队列里面加数据

     public ActionResult Index()
            {
                for (int i = 0; i < 600; i++)
                {
                    AsyncService.UerQueue.Add(new UserInfo { UserName=$"ma jiang -{i}" });
                }
                return View();
            }

    我的实际操作是在程序运行在7-10左右就停止IISExpress

    在Application_Start方法里面用:

    HostingEnvironment.QueueBackgroundWorkItem(x =>
    {
    AsyncService.Start();
    });

    运行结果如图:

    也就是说我的IISExpress退出后大概运行了30秒。

    调用:

    BackgroundTaskManager.Run(() =>
    {
    AsyncService.Start();
    }); 

    运行结果如图:

    也就是说我的IISExpress退出后大概运行了300秒

    这里推荐一个源码地址 HostingEnvironment.cs  通过阅读源码 已经证实Fire and Forget on ASP.NET里面的描述的准确性。虽然我的测试demo不够完善,但是并不影响结论:推荐使用  HostingEnvironment.RegisterObject方法

    demo下载

    该demo 在IIS下测试过, 比如:我们复制bin目录下的文件, 修改config文件 只要应用程序池 的进程ID 还存在,该方案一直可行,如

    经过测试,用如下code,只要IIS 应用程序池 进程ID不变(或者说 对应的进程ID存在),中间无论修改bin目录下文件,还是配置文件(也就是网上说的什么应用程序池自动回收的那些东东),都不会影响BackgroundTaskManager.Run里面的code。

    BackgroundTaskManager.Run(() =>
    {
    AsyncService.Start();
    });

  • 相关阅读:
    机器学习——EM算法
    机器学习——贝叶斯分类器
    机器学习——朴素贝叶斯法
    论文解读(SimCLR)《A Simple Framework for Contrastive Learning of Visual Representations》
    机器学习——数据增强
    机器学习——正则化方法Dropout
    ResNet
    机器学习——最小二乘法
    机器学习——K-Means算法
    机器学*——K*邻算法(KNN)
  • 原文地址:https://www.cnblogs.com/majiang/p/6287102.html
Copyright © 2011-2022 走看看