查看控制器是否仍在使用的MVC代码

本文关键字:MVC 代码 控制器 是否 | 更新日期: 2023-09-27 18:07:50

在我的MVC应用程序中,我有一个创建Model对象实例的控制器。在Model中,我有一个计时器,每个700ms执行一个函数。当我在我的网站中运行控制器时,即使在我关闭浏览器窗口后,我仍然看到计时器在运行。(定时器启动/停止串口连接,我有一个灯,当有通信时指示)。

在我完全重启IIS之前,通信实际上永远不会停止。

是否有某种方法可以检查控制器是否仍在使用中,从而在控制器不再活动时停止计时器?

模型代码:

public CheckPulses(int interval) {
    CheckPulsesTimer(interval);   
}
public void CheckPulsesTimer(int interval) {
    Timer timer = new Timer();
    timer.Enabled = true;
    timer.AutoReset = true;
    timer.Interval = interval;
    timer.Elapsed += new ElapsedEventHandler(GetPulses);
}

这里是Controller代码:

public ActionResult Index() {
    CheckPulses Pulses = new CheckPulses(700);
    return View();
}

我想也许我应该在GetPulses事件中添加一些东西,每次计时器间隔到期时都会发生,并检查控制器是否仍在使用中。如果不是,停止计时器。然而,我不知道如何写那张支票。有人能给我指个方向吗?

查看控制器是否仍在使用的MVC代码

我认为这里的核心问题是你对什么是控制器"在使用"的理解。

你似乎在想象以下内容:

  1. 用户输入URL,浏览器连接服务器。
  2. 服务器将请求路由到MVC控制器,该控制器与浏览器保持连接,并使用此连接响应每个后续请求。
  3. 用户关闭他们的浏览器,或者导航离开-控制器关闭连接,并处理。
然而,这不是实际发生的事情。Web流量通常是一系列孤立的、单独的请求/响应对。浏览器和服务器之间没有持续的连接。

更正确的顺序是这样的:

  1. 用户输入你的URL,浏览器通过端口80连接到你的服务器(https为443),传递一个有效的HTTP请求,包含URL, HTTP动词和其他信息。
  2. 您的服务器使用HTTP请求的信息请求路由到特定的可执行代码(在这种情况下,您的Controller的特定Action方法)。
  3. 为了执行,服务器创建一个Controller的实例,然后使用HTTP请求的信息作为参数,触发它的Action方法。
  4. 执行Controller代码,并向浏览器发送HTTP响应消息。
  5. Controller.Dispose() 'd由ControllerFactory

你遇到的问题不是由你的Controller"活跃"引起的——因为这不是Controller做的事情。相反,您在Model中创建了Timer,因此Model继续存在于内存中,无法被GarbageCollection杀死。

实际上,可以这样考虑:

你的Controller是作为一个工厂。当你调用它的Index方法时,相当于告诉工厂"生产1个Model"。一旦Model下线,工厂可以自由关闭,关灯,并让所有工人回家(Controller.Dispose() 'd)。

然而,Model仍然存在于内存中。在大多数情况下,一旦Model超出作用域,它可能会因为GarbageCollection而死亡——但是因为它里面有一个活动的Timer,所以有些东西阻止了该进程的执行——所以Model继续存在于服务器的内存中,在每次计时器到期时愉快地一次又一次地触发它的代码。

请注意,这个与用户是否还在你的网站上,或者他们的浏览器是否还打开等无关。它与变量作用域的性质和服务器上的GarbageCollection有关。您现在已经启动了一个进程,该进程将一直持续到被告知停止为止。

一个可能的解决方案:

为了解决这个问题,你可以考虑如下:

  1. 在Singleton对象中创建Timer。比如:

    public static class ConnectionManager {
        private static bool initialized = false;
        private static DateTime lastStartedAt = DateTime.Now;
        private static Timer timer = null;
        private static void Initialize() {
            if (timer == null) {
                timer = new Timer() {
                    AutoReset = true,
                };
                timer.Elapsed += new ElapsedEventHandler(GetPulses);
            }
        }
        public static void Start(int interval) {
            lastStartedAt = DateTime.Now;
            Initialize(); // Create a timer if necessary.
            timer.Enabled = true;
            timer.Interval = interval;
        }
        public static void Stop() {
            timer.Enabled = false;
        }
    }
    
  2. Controller更改为如下内容:

    public ActionResult Index() {
        ConnectionManager.Start(700);
        return View();
    }
    
  3. 当您处理Timer事件的过期时,检查lastStartedAt事件发生的时间。

  4. 如果大于X分钟,则不处理,触发ConnectionManager.Stop()

这将使您能够在滚动到期时保持串行活动轮询。换句话说,每次用户请求您的Index页面时,您将刷新计时器,并确保您正在侦听。但是,在X分钟之后,如果没有用户发出请求,您可以简单地关闭计时器和相关端口。

您可能没有停止或处置计时器。这将导致它不被垃圾收集,并在应用程序运行期间保持活动状态。

你应该在控制器的dispose方法中停止并处置Timer。

您有几个选择:

  1. 在控制器上重写Dispose方法,并调用脉冲。Dispose()
  2. 重写控制器上的onactionperformed方法并执行处置
  3. 创建自定义动作过滤器并实现OnActionExecuted方法并将其分配给控制器或动作。(你可以将模型的引用放入TempData中,然后在ActionFilter中检查是否filterContext.Controller。TempData["MyReferenceToModel"] = null,然后使用它来处置计时器)
  4. 在你的模型中实现IDisposable接口并在using语句中使用

希望这有帮助,Dima

你可以用JQuery+ MVC来停止Timer。

Jquery可以像这样响应页面的卸载事件:

$(window).unload(function() {
  alert('Handler for .unload() called.');
});

可以对控制器进行ajax调用。我们还需要创建一个属性来访问计时器。我假设你把你的Timer属性命名为MyTimer

Timer MyTimer { get; set; }

所以你需要创建一个返回void并调用Timer的Stop()方法的控制器。(HttpPost)public void KillTimer(){MyTimer.Stop ();}

现在,如果您向我们之前创建的卸载事件添加一个Ajax调用,那么我们应该能够在页面关闭时终止计时器。

$.ajax(
{
   type: "POST",
   url: "/Home/Index",
   ,
   success: function(result)
    {
        alert("Timer Closed");
    },                
   error : function(req, status, error)
   {
        alert("Sorry! We could not receive your feedback at this time.");   
   }
});

不需要成功和错误函数。我把它们包括进来只是为了演示。我还猜你的控制器的名字是Home。如果URL不同,则需要更新URL。您可以使用纯javascript来完成此操作。JQuery帮助您避免编写大量乏味的浏览器兼容性代码。(我听说歌剧的卸货部分很痛苦)

为了解决潜在的浏览器崩溃和意外事件的问题,你可以连接你的控制器来检查计时器是否超过了最大时间限制。

祝你好运!

来源:

JQuery卸载()

调用ASP。. NET MVC Actions from JavaScript using jQuery

JQuery Ajax ()