MVC 5 - IIS停止任务线程

时间:2016-03-02 15:16:11

标签: c# multithreading iis asp.net-mvc-5

我有一个线程可以在特定时间发送事件来运行程序。

我确实希望网站能够完全控制流程,这就是为什么我将它作为一个循环的长期线程构建到网站中的原因。

问题是我计划在特定时间执行任务,它几乎是随机发生的(可能是在我加载页面时)。看起来好像Web应用程序在使用它之前会睡眠所有线程。

以下是代码:

public void run()
{
    Task.Factory.StartNew(() =>
    {
        while (true)
        {
            var lastDate = InternalEventLogger.GetLastDateTime();
            if (DateTime.Now >= lastDate.AddDays(1))
            {
                System.Diagnostics.Debug.WriteLine(DateTime.Now);
                System.Diagnostics.Debug.WriteLine(lastDate.AddDays(1));
                InternalEventLogger.RefreshLog();
            }
            bool needUpdate = false;
            System.Diagnostics.Debug.WriteLine("this");
            List<Event> tempList = new List<Event>(this.evtList.getList());
            foreach (Event evt in this.evtList.getList())
            {
                if (!evt.status.Equals("success"))
                    continue;
                if (evt.nextRun <= DateTime.Now)
                {
                    var tempEvt = evt;
                    System.Diagnostics.Debug.WriteLine("time to run: "+evt.name);
                    tempList.Remove(evt);
                    tempEvt.nextRun = evt.nextRun.AddMinutes(evt.interval);
                    tempEvt.lastRan = DateTime.Now;
                    tempList.Add(tempEvt);
                    needUpdate = true;
                    if (tempEvt.runLocation != null) 
                    Task.Factory.StartNew(() =>
                    {
                        Process p = new Process();
                        p.StartInfo.FileName = tempEvt.runLocation;
                        p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                        p.Start();
                        string output = p.StandardOutput.ReadToEnd();
                        string err = p.StandardError.ReadToEnd();
                        InternalEventLogger.WriteLog(output);
                        InternalEventLogger.WriteLog("// ------------- ERROR -------------- \n" + err);
                        p.WaitForExit();
                    });
                }
            }
            if (needUpdate)
            {
                this.evtList.setList(tempList);
                this.evtList.serialize(ConfigurationManager.AppSettings["xmlEventLocation"]);
            }
            Thread.Sleep(10000);
        }
    }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default);
}

来自:

private static void RegisterServices(IKernel kernel)
{
    evtManager = new EventManager(ConfigurationManager.AppSettings["xmlEventLocation"]);
    evtManager.run();
    // Initalize Event Logger
    new InternalEventLogger();
} 

这是一张显示时间问题的图片: enter image description here

下面的IIS设置
只有在访问时才开始执行任务。

enter image description here

2 个答案:

答案 0 :(得分:0)

在IIS管理器中打开该设置对话框。 确保你有:

  1. 启动模式= AlwaysRunning
  2. 空闲超时(分钟)= 0
  3. 对于您正在使用的应用程序池 - 测试设置,以确保您正在编辑正确的池。

    如果你有这个,你的应用程序应该一直在运行,但还有一件事 - 回收 - 在该设置对话框的底部,根据需要设置回收。可能是您使用默认设置,但如果您不了解回收,则可能会让您感到惊讶,因此请确保您了解它并根据需要配置设置。

答案 1 :(得分:0)

是的,你是对的,IIS托管不存储线程,因为所有Web应用程序必须做的是处理请求并提供响应。如果你想按计划运行任务,你真的不应该使用Web应用程序,因为它会在发送响应后取消所有后台线程。

我建议您更改您的体系结构,并创建一个Windows服务(如守护进程),它将在系统启动后自动启动,并且可以更轻松地控制事件触发。

如果由于某种原因你需要这种方法的Web界面,你可以在你的web应用程序和windows服务之间使用WCF绑定(通过TCP / IP或命名管道或其他),但你的方法不会'适用于Web应用程序。

我还要指出这段代码:

while (true)

是一个坏主意 - 在这种情况下,您应该使用CancellationToken来完成任务。