我有一个应用程序,允许用户使用我们自己的语言编写自己的代码,这有点像C++。但是,我们遇到了问题,有时我们的用户会意外地在脚本中写入无限循环。一旦脚本进入无限循环,他们可以退出的唯一方法就是关闭应用程序并重新启动,可能会失去工作。我想添加一些方法,当用户意识到他的代码处于无限循环时,可以按F10之类的特殊键,代码就会跳出循环。但是我希望不用在脚本运行时执行大量的检查。最好,我希望有一个单独的“调试器”线程,它大部分是空闲的,但作为其任务之一,它监听F10键,当它获得F10键时,它将导致脚本运行时线程抛出异常,以便它将停止执行脚本。所以我的问题是,有没有办法让一个线程导致另一个线程抛出异常?我的应用程序是用C++编写的。跨线程异常抛出
跨线程异常抛出
回答
这是可能的。例如,在单独的线程,隐藏的窗口和WM_HOTKEY中检测击键。调用SuspendThread()来冻结解释器线程。现在使用GetThreadContext()获取解释器线程的CPU寄存器。将CONTEXT.Eip修改为一个函数的地址并调用SetThreadContext()。让该函数调用RaiseException()或抛出一个C++异常。 ResumeThread()和繁荣。
简短的回答 - 没有。
如果你的应用程序在Windows上运行,也许你可以从这个“调试器”的步伐发送消息,并在主要的消息循环?
如果脚本实际上是由应用程序解释的,那么只要告诉解释器在发生某些用户事件时就停止执行。
该解决方案的问题是,为了做一个消息发送实现,我必须设置一个“侦听器”作为脚本解释器的一部分。目前,解释器只是执行该功能。消息循环在解释器之外实现。如果在函数中有一个无限循环,那么为了突破这个脚本,我将不得不在检查解释器中每条指令的执行之间的一条消息,也就是说,当(更多指令){检查F10,执行脚本指令}。这似乎是很多额外的不必要的检查,可能会减慢脚本执行速度。但如果这是唯一的解决方案,那么我想这就是它的原因。我仍然认为应该有更好的方法。也许脚本解释器需要在子线程上运行,而主线程继续它的消息循环,然后在获得F10时终止脚本解释器线程。
“这个解决方案的问题是,为了做一个消息发送实现,我必须在脚本解释器中设置一个'listener'”听起来很像“我想要这个新功能,但我不想不想改变代码来获取它。“对不起,但我认为你需要更改代码。 – 2009-01-15 22:42:24
终止线程是不安全的,因为它可能使用跨整个进程共享的资源。
终止整个过程并不安全,但这不会帮助你。
解决此问题的一种更安全的方法是让解释器定期检查事件并将停止事件视为终止事件(或至少溢出到更高的循环)。对于Windows,您也可以将APC排队到调用RaiseException(...)
或引发异常的那个线程(尽管我会避免后者,因为它跨越了API边界),但是这也意味着线程将把自己放入一个可警告的状态。我并不真的推荐它。
无论您是否明确编码,都需要在消息循环中检查“中断”变量。如果你通过一个简单的volatile int
实现这个,你将会有一个非常简单的测试和很少的开销。
- 1. 跨线程异常
- 2. 获取Visual Studio以跨线程抛出异常
- 3. 线程中抛出错误(异常)
- 4. 的std ::线程创建抛出异常
- 5. 在UI线程上抛出异常
- 6. junit在线程抛出异常
- 7. 抛出异常的线程C#
- 8. Titan中的多线程抛出异常
- 9. 跨线程调用异常
- 10. 魔术异常抛出抛出异常
- 11. 致命异常:java.lang.IllegalStateException:致命异常在Scheduler.Worker线程上抛出
- 12. 中断主调用线程如果子线程抛出异常
- 13. 异常抛出异常
- 14. 抛出异常
- 15. 抛出异常
- 16. 抛出异常
- 17. 异常抛出
- 18. HttpURLConnection抛出异常
- 19. PerformanceCounter抛出异常
- 20. BIGDECIMAL抛出异常
- 21. 异常抛出Manatee.Trello.RestSharp.RestSharpResponse
- 22. Android抛出异常
- 23. IsDBNull抛出异常
- 24. NHibernate抛出异常
- 25. VB.NET抛出异常
- 26. RapidXML抛出异常
- 27. System.Transactions.Diagnostics.DiagnosticTrace抛出异常
- 28. socket.connect抛出异常
- 29. scanf_s抛出异常
- 30. 异常抛出InputOutputArray
试过这个,它工作得很好。谢谢!!! – 2009-03-23 20:56:17