![](/img/trans.png)
[英]How add custom AuthorizeAttribute for some specific Controller use code on MVC?
[英]MVC code to see whether or not a Controller is still in use
在我的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);
}
这是控制器代码:
public ActionResult Index() {
CheckPulses Pulses = new CheckPulses(700);
return View();
}
我想也许我应该只向GetPulses
事件添加一些东西,该事件在每次定时器间隔到期时发生,并检查该控制器是否仍在使用中。 如果不是,请停止计时器。 但是,我不确定如何写支票。 谁能指出我正确的方向?
我认为这里的核心问题在于您对“正在使用”的控制器的理解。
似乎您正在想象以下内容:
但是,实际情况并非如此。 Web流量通常是一系列隔离的,单独的请求/响应配对。 浏览器和服务器之间没有正在进行的连接。
更正确的顺序如下所示:
Controller
的特定Action
方法)。 Controller
的Instance,然后使用HTTP请求的信息作为参数来触发它的Action
方法。 Controller
代码将执行,并且HTTP响应消息将发送回浏览器。 Controller
由ControllerFactory
.Dispose()
。 您遇到的问题不是由Controller
处于“活动状态”引起的-因为那不是Controller
所做的。 相反,您正在Model
创建一个Timer
,因此该Model
继续存在于内存中,无法被GarbageCollection
杀死。 有关更多详细信息,请参见此答案 。
本质上,应这样考虑:
您的Controller
正在充当工厂。 当您调用其Index
方法时,等效于告诉工厂“生产1个Model
”。 Model
推出工厂后,工厂可以自由关闭,关闭灯,并将所有工人送回家( Controller
为.Dispose()
'd)。
但是, Model
仍然存在于内存中。 在大多数情况下,一旦超出范围,该Model
应该由于GarbageCollection
而消失-但由于其中有一个活动的Timer
,因此某些东西阻止了该进程的执行-因此该Model
继续存在于服务器的内存中,在每次计时器到期时愉快地一次又一次地触发其代码。
请注意,这无关与用户是否仍是您的网站,或者他们的浏览器是否仍处于打开状态等,与变量范围和性质做GarbageCollection
的服务器上。 现在,您已经开始了一个过程,该过程将继续直到被告知停止。
潜在的解决方案:
为了解决此问题,您可以考虑以下因素:
在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; } }
将您的Controller
更改为以下内容:
public ActionResult Index() { ConnectionManager.Start(700); return View(); }
处理Timer
事件的到期时,请检查lastStartedAt
事件发生多久了。 如果超过X
分钟,则不进行处理,并触发ConnectionManager.Stop()
。
这将使您能够在滚动到期时保持串行活动轮询。 换句话说,每次用户请求您的“ Index
页面时,您将刷新计时器,并确保您正在收听。 但是,在X
分钟后,如果没有用户提出请求-您只需关闭计时器和相关的端口即可。
您可能没有停止或处置计时器。 这将导致它不会被垃圾回收,并在应用程序保持运行期间保持活动状态。
您应该在Controller的Dispose方法中停止并处置Timer。
您有几种选择:
希望这会有所帮助,迪玛
您可以使用JQuery + MVC停止Timer。
jQuery可以响应页面的unload事件,如下所示:
$(window).unload(function() {
alert('Handler for .unload() called.');
});
您可以对控制器进行ajax调用。 我们还需要创建一个属性来访问计时器。 我假设您将计时器属性称为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可以帮助您避免编写大量繁琐的浏览器兼容性代码。 (我听说歌剧在卸载部分很痛苦)
为了解决潜在的浏览器崩溃和意外事件的问题,您可以连接控制器以检查计时器是否超过了最大时间限制。
祝好运 !
资料来源:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.