如何限制任务在 .Net 下运行的时间?
我知道有多种方法可以限制任务在 .Net 下运行的时间,我想知道是否还有其他我错过的方法或对我之前使用的方法的修改/改进。
如果我不清楚方法论到底如何运作,我会提出一些问题。
我知道但我自己不一定使用的现有方法:
- 创建一个线程,轮询它在一定时间内完成,然后终止线程。这个解决方案不是很好,因为它依赖于 ThreadAbortException ,这有点令人讨厌,如果我记得你不能保证代码将在哪里退出,即它可能会留下未修改的资源正在使用等。
- 使用
IAsyncResult
模式,这样做的问题是您可以等待一定的时间,但没有一种简单的方法来表明您希望中止请求,因此您必须依赖于设置一个布尔标志(或类似的标志),在异步代码内部检查并导致其停止。这里的问题是,如果异步代码卡在代码的某个部分,它可能会在实际终止之前继续运行一段时间。 - 我经常看到人们推荐
BackgroundWorker
来进行异步操作,但是您可以在 ASP.Net 下使用它吗(我假设是这样),并且它是否有一种简单的方法可以在一段时间后终止异步进程? - 使用 .Net 4.0 中的任务 API(目前我的所有工作都仅限于 .Net 3.5,所以这对我来说不是一个选择)。快速阅读 MSDN 文档后发现,您似乎可以使用 CancellationToken 轻松取消任务,但是取消的生效速度有多快,以及是否确保任何
finally
块都能得到叫。
欢迎所有解决方案/建议/方法
I know there are various ways to limit how long a task runs under .Net and I wondered if there are any others I've missed or modifications/improvements to the methods I've used previously.
Where I am unclear on how exactly a methodology functions I have included questions on it.
Existing methods I'm aware of though not necessarily used myself:
- Create a
Thread
, poll for it to finish for a certain time then kill the thread. This solution is not great as it relies onThreadAbortException
's which are somewhat nasty and if I remember you have no guarantee where you'll code will exit i.e. it may leave unamanged resources in use etc. - Use the
IAsyncResult
pattern, the problem with this is that you can wait for a certain amount of time but there isn't a simple way to signal that you want the request to be aborted so you have to rely on setting a boolean flag (or similar) which is checked for inside the async code and causes it to halt. Issue here is that if the async code is stuck in a certain section of the code it may continue to run for some time before it actually terminates. - I've often seen people recommend
BackgroundWorker
for async stuff but can you use this under ASP.Net (I'd assume so) and does it have a simple way of terminating the async process after a certain time? - Use the Task API in .Net 4.0 (currently all my work is constrained to .Net 3.5 so not an option for me). From a quick read of the MSDN documentation it looks like you can easily cancel a Task using the
CancellationToken
but how quickly does a cancellation take affect and does it ensure anyfinally
blocks get called.
All solutions/suggestions/methodologies welcome
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
最安全的取消形式始终是合作。
我建议永远不要终止线程(通过 ThreadAbortException)。如果您绝对别无选择,那么请将该代码作为一个单独的进程,这样就可以彻底杀死它。 AppDomains 是一个好主意,但它们不符合现实世界。
IAsyncResult
、BackgroundWorker
和CancellationToken
都是协作取消的形式。所以它们都非常干净(不会丢失资源、调用finally
块……),但缺点是它们无法处理“流氓”代码。如果您正在编写后台任务代码,则只需使用
BackgroundWorker
或CancellationToken
。如果您必须使用可能的“流氓”代码,请将其包装在单独的进程中。BackgroundWorker
在 ASP.NET 中可以正常工作,并且它 支持合作取消。The safest form of cancellation is always cooperative.
I recommend never killing a thread (via
ThreadAbortException
). If you absolutely have no choice, then make that code a separate process instead, which can be cleanly killed. AppDomains were a nice idea, but they don't hold up to the real world.IAsyncResult
,BackgroundWorker
, andCancellationToken
are all forms of cooperative cancellation. So they are all very clean (not losing resources, callingfinally
blocks, ...), but have the disadvantage that they can't handle "rogue" code.If you are writing the background task code, then just use
BackgroundWorker
orCancellationToken
. If you must work with possibly "rogue" code, then wrap it in a separate process.BackgroundWorker
will work just fine in ASP.NET, and it supports cooperative cancellation.4 中的取消标记和 2 中的布尔标志是相同类型的机制。在这两种情况下,任务都必须合作并定期检查标志。 4 的优点是您拥有标准化标志,而不是创建自己的标志。
中止线程是邪恶的,但如果您的代码编写得仔细,则可以管理。特别是它很容易破坏全局状态。
中止线程的安全版本是在不同的应用程序域中运行它。然后,一旦线程被终止,您就卸载应用程序域。如果所有非托管资源都有正确的关键终结器/使用 SafeHandles,这将以安全的方式工作。
The cancellation token from 4 and the boolean flag from 2 are the same kind of mechanism. In both cases the task has to cooperate and check the flag regularly. The advantage of 4 is that you have a standardized flag instead of creating your own.
Aborting threads is evil, but manageable if your code is written carefully. In particular it's easy to corrupt global state.
The safe version of aborting a thread is running it in a different app-domain. Then you unload the app-domain once the thread has been killed. This will work in a safe way if all your unmanaged resources have correct critical finalizers/use SafeHandles.