如何中止 .NET 任务?
情况是这样的,我正在编写代码战争竞赛的框架。当代码运行时,每轮它都会调用每个参赛者提供的库中的方法。比赛规则是该方法必须在 1 秒内返回,否则我们将终止调用它们的任务。然后我们使用该回合的默认结果。
该方法不支持取消,因为我们不能相信被调用的代码会响应取消。我们需要终止线程,因为如果我们有 10 或 20 个被忽略的后台任务,那么接下来的所有调用将在每次调用上提供更少的时钟周期,并且之前花费不到 1 秒的方法现在需要更多的时钟周期。
从好的方面来说,我们要杀死的方法应该没有打开的资源等,因此中止不应该留下任何挂起的东西。
更新:这里需要记住两件事。首先,这就像一场游戏 - 因此性能很重要。其次,工作线程不太可能打开任何资源。如果其中一个被调用的方法时间过长,我需要中止它并快速继续。
Here's the situation, I am writing the framework for a code war contest. As the code runs, for each turn, it calls a method in the library provided by each contestant. The rules of the contest is the method must return in 1 second or we kill the task calling them. We then use a default result for that turn.
The method has no support for a cancel because we cannot trust the called code to respond to a cancel. And we need to kill the thread because if we have 10 or 20 ignored background tasks then all calls going forward will provide fewer clock cycles on each call and methods that before took less than 1 second now take more.
On the plus side, the method we're killing should have no resources open, etc. so an abort should not leave anything hanging.
Update: Two things to keep in mind here. First, this is like a game - so performance is important. Second, the worker thread is unlikely to have any resources open. If one of the called methods goes overlong, I need to abort it and move on quickly.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您应该以低权限在每个参赛者自己的 AppDomain 中运行。这有几个优点:
即使您更喜欢终止线程而不是卸载 AppDomain,我仍然会将每个参赛者放入 AppDomain 中以获得隔离。
不幸的是 Thread.Abort 还不够。它仍然执行
finally
子句,可以根据需要执行任意长的时间。You should run each contestant in his own AppDomain with low privileges. This has several advantages:
Even if you prefer killing the thread over unloading the AppDomain I'd still put each contestant into an AppDomain to get the isolation.
Unfortunately
Thread.Abort
is not enough. It still executesfinally
clauses which can take as long as they want.我建议您在第二个进程中运行代码,并仔细定义与其通信的接口,以确保它可以处理未收到响应的情况。大多数操作系统都被设计为在杀死进程后能够很好地进行清理。
对于通信,您可能应该避免使用 .NET 远程处理,因为这可能会在服务器端处于不一致的状态。其他一些选择:套接字、命名管道、Web 服务。
I would recommend that you run the code in a second process and carefully define the interface for communicating with it to ensure that it can handle not receiving a response. Most operating systems are designed to clean up fairly well after a killing a process.
For communication, you should probably avoid .NET remoting, as that seems likely to be left in an inconsistent state on the server side. Some other choices: sockets, named pipes, web service.
Thread.Interrupt() 方法可能就是您正在寻找的。
正如 MSDN 文档所说,“如果该线程当前没有在等待、睡眠或连接状态下被阻塞,那么当它下次开始阻塞时,它将被中断。”
它不是中止,它强制正在运行的线程在线程进入等待状态时抛出 ThreadInterruptedException。
然后,您可以在另一个线程中使用带有超时的计时器来检查该线程是否真的不想终止,如果该线程拒绝在(例如 30 秒)内终止,您可以中止它。
Thread.Interrupt() method is maybe what you are looking for.
As the MSDN documentation says, "If this thread is not currently blocked in a wait, sleep, or join state, it will be interrupted when it next begins to block."
It is not an abort, it forces the running thread to throws ThreadInterruptedException when the thread enters in a wait state.
You can then use a timer in another thread with a timeout to check if the thread don't really want to terminate, if the thread refuses to terminate in, for example, 30 seconds, you can abort it.