问题描述
各位好,目前项目需要做一个数据同步的功能,而且是自动同步。我在application_start事件中添加了如下代码:protectedvoidApplication_Start(){.....//读取配置等代码AreaRegistration.RegisterAllAreas();//默认情况下对EntityFramework使用LocalDBDatabase.DefaultConnectionFactory=newSqlConnectionFactory(@"DataSource=(localdb)v11.0;IntegratedSecurity=True;MultipleActiveResultSets=True");Logger.ConfigureLog4Net(HttpContext.Current.Server.MapPath("~/log"),LogLevel.Info,LogLevel.Info);RegisterGlobalFilters(GlobalFilters.Filters);RegisterRoutes(RouteTable.Routes);//如果是平台,则启动,如果是控制中心,则不启动if(Application[SYSTEM_TYPE].ToString()=="1"){//判断平台类型if(!threadStarted){//线程是否已经启动infoTaskIdList=newList<int>();processTask=newProcessTask();threadProcessTask=newThread(newParameterizedThreadStart(processTask.ProcessTasks));threadProcessTask.Start(Application);开启线程。threadStarted=true;}}}
ProcessTasks方法如下:publicvoidProcessTasks(objectapplicationState){HttpApplicationStateapplication=applicationStateasHttpApplicationState;while(true){IEnumerable<Da_Task>taskList=taskBll.GetListByPage("andnvl(dt_status,'1')='1'","asc",0,20);if(taskList==null){continue;}taskList=taskList.OrderBy(p=>p.DT_ID);stringdealinfo="";foreach(Da_TasktaskintaskList){try{//保存Application全局UserID;这里会不会有问题?application["userid"]=task.DT_RCRE_USER;//模拟发送POST/GET请求,以便执行数据操作stringretstr=PostData(localHost+task.DT_Destination,task.DT_Data);IDictionary<string,JToken>parsedObject=null;try{parsedObject=JsonConvert.DeserializeObject(retstr)asJObject;}catch{parsedObject=JsonConvert.DeserializeObject("{result:-3}")asJObject;}//业务逻辑代码省略......}catch(Exceptione){//写错误日志,停止任务执行Loggerlog=Logger.GetLogger(this.GetType());log.Error("执行任务时发生错误",e);//break;}}Thread.Sleep(ProcessTaskTime);//执行完毕等待}}
现在的情况是这样的,我使用的是VS2012,框架是MVC,我配置的是调试使用本地IIS,而不是IISExpress,但是当我调试在ProcessTasks中断点时,发现有两个线程进入到该方法,导致调试出现问题,我猜想的原因是:一个线程是IIS的线程,另一个是我的调试线程。但是我疑惑的是Application_Start到底运行了几次???我已经通过threadStarted来判断,为什么还是有两条线程呢?请高手讲解??
解决方案
解决方案二:
网站天生是多线程的,你不要把网站当单机版玩
解决方案三:
application_start事件应该是只执行一次的啊……不懂了,就跟当初我怎么都抓不到application_end事件一样,完全不懂了
解决方案四:
application_start理论上的确是只运行一次但是网站在某些情况会自动重启然后再次调用application_start而线程却没有关闭所以会有两个线程
解决方案五:
threadStarted判断这里,尝试先lock一下,重入了,很可能是因为同事有2个线程调用了Application_Start而在threadStarted赋值之前,两个线程都进入了if判断,lock一下应该可以解决重入问题。另外多次调用Application_Start很可能是调试的原因,尝试打日志,软件直接在IIS上运行一下,可能就不会多次调用了。当然,IIS重启也是经常发生的事情。。。。。但是第一次就直接进入2次,应该可能性不是很大。下面这句是复制来的:你看下应用程序池属性里回收中回收工作进程和性能中空闲超时是否启用了?不想重复运行Application_Start就把复选框不要选中
解决方案六:
引用1楼Z65443344的回复:
网站天生是多线程的,你不要把网站当单机版玩
大神你这等于没说,我当然知道网站天生多线程,你要是知道一些端倪,烦请讲解一下,为什么我这调试时会有两个线程进入方法?使用IIS调试时,application_start执行了几次?
解决方案七:
Asp.net如果进程池被回收了,就会重新运行application_start所以就有可能运行多次。
解决方案八:
引用6楼wyd1520的回复:
Asp.net如果进程池被回收了,就会重新运行application_start所以就有可能运行多次。
按理说如果进程池被回收,则进程创建的线程也应该被回收才对啊,那就算重新启动应用运行application_start也应该还是一个线程。
解决方案:
引用7楼ZackHoo的回复:
Quote: 引用6楼wyd1520的回复:
Asp.net如果进程池被回收了,就会重新运行application_start所以就有可能运行多次。按理说如果进程池被回收,则进程创建的线程也应该被回收才对啊,那就算重新启动应用运行application_start也应该还是一个线程。
进程池回收的不是他的整个进程不等于exe退出,是拉圾回收,一般会在进程池里面设定的内存达到一定的值时进程池开始回收,而你的线程是一直运行下去的,所以不会被回收。
解决方案:
!threadStarted你这个是静太对象?不是的话就是被回收执行完这个对象就没啥用了