如果我 运行 时间太长,我该如何终止自己?
How can i terminate myself if i run too long?
我有一个定期 运行 的应用程序(这是一项计划任务)。该任务每分钟启动一次,通常只需几秒钟即可完成其业务,然后退出。
但应用程序挂起的几率约为 80,000 分之一(每两三个月)。根本原因是因为我们正在使用 Microsoft ServerXmlHttpRequest 组件来执行一些工作,并且 . The virtue of ServerXmlHttpRequest over XmlHttpRequest is that the latter is not recommended for important scenarios,例如可靠性和安全性很重要的地方(无人值守的服务器组件也是如此):
The ServerXMLHTTP
object offers functionality similar to that of the XMLHTTP
object. Unlike XMLHTTP
, however, the ServerXMLHTTP
object does not rely on the WinInet control for HTTP access to remote XML documents. ServerXMLHTTP
uses a new HTTP client stack. Designed for server applications, this server-safe subset of WinInet offers the following advantages:
- Reliability — The HTTP client stack offers longer uptimes. WinInet features that are not critical for server applications, such as URL caching, auto-discovery of proxy servers, HTTP/1.1 chunking, offline support, and support for Gopher and FTP protocols are not included in the new HTTP subset.
- Security — The HTTP client stack does not allow a user-specific state to be shared with another user's session. ServerXMLHTTP provides support for client certificates.
作业正在 运行 作为计划任务。我需要定期继续 运行 的任务;如果现有进程已死,则将其杀死。
Windows 任务计划程序确实有一个选项可以强制关闭 运行 太长的任务:
该方法的唯一缺点是它根本不起作用 - 它根本不会停止任务。挂起的进程保持运行ning.
鉴于我不能相信 Microsoft ServerXmlHttpRequest 不会任意锁定,并且任务计划程序无法终止计划任务,我需要一些方法来自己完成。
职位
我尝试使用 Job Objects API:
A job object allows groups of processes to be managed as a unit. Job objects are namable, securable, sharable objects that control attributes of the processes associated with them. A job can enforce limits such as working set size, process priority, and end-of-job time limit on each process that is associated with the job.
那个音符听起来正是我所需要的:
A job can enforce limits such as end-of-job time limit on each process that is associated with the job.
该方法的唯一缺点是它不起作用。工作不能对过程施加时间限制。他们只能强加一个 user time limit on a process:
PerProcessUserTimeLimit
If LimitFlags specifies JOB_OBJECT_LIMIT_PROCESS_TIME, this member is the per-process user-mode execution time limit, in 100-nanosecond ticks.
如果进程处于空闲状态(例如,像 ServerXmlHttpRequest 一样处于 MsgWaitForSingleObject 状态),那么它将不会累积 user 时间。我测试了它。我创建了一个时间限制为 1 秒的作业,并将我的 self 进程放入其中。只要我不在我的测试应用程序周围移动鼠标,它就会很高兴地在那里停留超过一秒钟。
看门狗线程
考虑到我的主线程被无限期阻塞,我能想到的唯一其他技术是另一个线程。我能想到的唯一解决方案是生成另一个线程,该线程将休眠三分钟,然后 ExitProcess:
Int32 watchdogTimeoutSeconds = FindCmdLineSwitch("watchdog", 0);
if (watchdogTimeoutSeconds > 0)
Thread thread = new Thread(KillMeCallback, new IntPtr(watchdogTimeoutSeconds));
void KillMeCallback(IntPtr data)
{
Int32 secondsUntilProcessIsExited = data.ToInt32();
if (secondsUntilProcessIsExited <= 0)
return;
Sleep(secondsUntilProcessIsExited*1000); //seconds --> milliseconds
LogToEventLog(ExtractFilename(Application.ExeName),
"Watchdog fired after "+secondsUntilProcessIsExited.ToString()+" seconds. Process will be forcibly exited.", EVENTLOG_WARNING_TYPE, 999);
ExitProcess(999);
}
这行得通。唯一的缺点是 it's a bad idea.
谁能想到更好的办法?
编辑
现在我将实现一个
Contoso.exe /watchdog 180
因此进程将在 180 秒后退出。这意味着持续时间是可配置的,或者可以在现场轻松地完全删除。
我使用了在命令行上向我的进程传递一个特殊的 WatchDog 参数的路径;
>Contoso.exe /watchdog 180
在初始化过程中,我检查是否存在 WatchDog
选项,其后为整数秒数:
String s = Toolkit.FindCmdLineOption("watchdog", ["/", "-"]);
if (s <> "")
{
Int32 seconds = StrToIntDef(s, 0);
if (seconds > 0)
RunInThread(WatchdogThreadProc, Pointer(seconds));
}
和我的线程程序:
void WatchdogProc(Pointer Data);
{
Int32 secondsUntilProcessIsExited = Int32(Data);
if (secondsUntilProcessIsExited <= 0)
return;
Sleep(secondsUntilProcessIsExited*1000); //seconds -> milliseconds
LogToEventLog(ExtractFileName(ParamStr(0)),
Format("Watchdog fired after %d seconds. Process will be forcibly exited.", secondsUntilProcessIsExited),
EVENTLOG_WARNING_TYPE, 999);
ExitProcess(2);
}
我有一个定期 运行 的应用程序(这是一项计划任务)。该任务每分钟启动一次,通常只需几秒钟即可完成其业务,然后退出。
但应用程序挂起的几率约为 80,000 分之一(每两三个月)。根本原因是因为我们正在使用 Microsoft ServerXmlHttpRequest 组件来执行一些工作,并且
The
ServerXMLHTTP
object offers functionality similar to that of theXMLHTTP
object. UnlikeXMLHTTP
, however, theServerXMLHTTP
object does not rely on the WinInet control for HTTP access to remote XML documents.ServerXMLHTTP
uses a new HTTP client stack. Designed for server applications, this server-safe subset of WinInet offers the following advantages:
- Reliability — The HTTP client stack offers longer uptimes. WinInet features that are not critical for server applications, such as URL caching, auto-discovery of proxy servers, HTTP/1.1 chunking, offline support, and support for Gopher and FTP protocols are not included in the new HTTP subset.
- Security — The HTTP client stack does not allow a user-specific state to be shared with another user's session. ServerXMLHTTP provides support for client certificates.
作业正在 运行 作为计划任务。我需要定期继续 运行 的任务;如果现有进程已死,则将其杀死。
Windows 任务计划程序确实有一个选项可以强制关闭 运行 太长的任务:
该方法的唯一缺点是它根本不起作用 - 它根本不会停止任务。挂起的进程保持运行ning.
鉴于我不能相信 Microsoft ServerXmlHttpRequest 不会任意锁定,并且任务计划程序无法终止计划任务,我需要一些方法来自己完成。
职位
我尝试使用 Job Objects API:
A job object allows groups of processes to be managed as a unit. Job objects are namable, securable, sharable objects that control attributes of the processes associated with them. A job can enforce limits such as working set size, process priority, and end-of-job time limit on each process that is associated with the job.
那个音符听起来正是我所需要的:
A job can enforce limits such as end-of-job time limit on each process that is associated with the job.
该方法的唯一缺点是它不起作用。工作不能对过程施加时间限制。他们只能强加一个 user time limit on a process:
PerProcessUserTimeLimit
If LimitFlags specifies JOB_OBJECT_LIMIT_PROCESS_TIME, this member is the per-process user-mode execution time limit, in 100-nanosecond ticks.
如果进程处于空闲状态(例如,像 ServerXmlHttpRequest 一样处于 MsgWaitForSingleObject 状态),那么它将不会累积 user 时间。我测试了它。我创建了一个时间限制为 1 秒的作业,并将我的 self 进程放入其中。只要我不在我的测试应用程序周围移动鼠标,它就会很高兴地在那里停留超过一秒钟。
看门狗线程
考虑到我的主线程被无限期阻塞,我能想到的唯一其他技术是另一个线程。我能想到的唯一解决方案是生成另一个线程,该线程将休眠三分钟,然后 ExitProcess:
Int32 watchdogTimeoutSeconds = FindCmdLineSwitch("watchdog", 0);
if (watchdogTimeoutSeconds > 0)
Thread thread = new Thread(KillMeCallback, new IntPtr(watchdogTimeoutSeconds));
void KillMeCallback(IntPtr data)
{
Int32 secondsUntilProcessIsExited = data.ToInt32();
if (secondsUntilProcessIsExited <= 0)
return;
Sleep(secondsUntilProcessIsExited*1000); //seconds --> milliseconds
LogToEventLog(ExtractFilename(Application.ExeName),
"Watchdog fired after "+secondsUntilProcessIsExited.ToString()+" seconds. Process will be forcibly exited.", EVENTLOG_WARNING_TYPE, 999);
ExitProcess(999);
}
这行得通。唯一的缺点是 it's a bad idea.
谁能想到更好的办法?
编辑
现在我将实现一个
Contoso.exe /watchdog 180
因此进程将在 180 秒后退出。这意味着持续时间是可配置的,或者可以在现场轻松地完全删除。
我使用了在命令行上向我的进程传递一个特殊的 WatchDog 参数的路径;
>Contoso.exe /watchdog 180
在初始化过程中,我检查是否存在 WatchDog
选项,其后为整数秒数:
String s = Toolkit.FindCmdLineOption("watchdog", ["/", "-"]);
if (s <> "")
{
Int32 seconds = StrToIntDef(s, 0);
if (seconds > 0)
RunInThread(WatchdogThreadProc, Pointer(seconds));
}
和我的线程程序:
void WatchdogProc(Pointer Data);
{
Int32 secondsUntilProcessIsExited = Int32(Data);
if (secondsUntilProcessIsExited <= 0)
return;
Sleep(secondsUntilProcessIsExited*1000); //seconds -> milliseconds
LogToEventLog(ExtractFileName(ParamStr(0)),
Format("Watchdog fired after %d seconds. Process will be forcibly exited.", secondsUntilProcessIsExited),
EVENTLOG_WARNING_TYPE, 999);
ExitProcess(2);
}