.Net 异步委托中止
Posted
技术标签:
【中文标题】.Net 异步委托中止【英文标题】:.Net Asynchronous Delegate Abortion 【发布时间】:2012-06-08 22:42:55 【问题描述】:背景: 我的应用程序用于使用Selenium RC 服务器执行测试,当我对 Selenium 命令的调用没有返回来自 RC 的响应时,我偶尔会遇到问题服务器 - 然后它最终阻塞正在执行测试的线程。
示例代码:
Private Delegate Function DoCommand_Delegate(ByVal command As String, ByVal args() As String) As String
...
asyncCommand = New DoCommand_Delegate(AddressOf server.DoCommand)
asyncResult = asyncCommand.BeginInvoke(command, args, Nothing, Nothing)
Try
... (I have it use the AsyncWaitHandle to wait for periods of 10 seconds up to two minutes. At the end of each period it runs some checks for common problems that block Selenium from returning a response (modal dialogs) - I don't think that part is relevant to this question, it's just necessary.)
Finally
result = asyncCommand.EndInvoke(asyncResult)
...
在调用EndInvoke
时,工作代理已经完成或需要中止。大多数时候它已经有了响应,所以它工作得很好,但在极少数情况下 Selenium RC 的 DoCommand 不会返回,所以线程在那里被锁定。
最后,我的问题:是否有一种资源友好的方式来中止正在执行的委托,或者我是否需要将其转换为使用可以中止和释放的手动控制线程? p>
注意:这不是关于 Selenium 的问题,只是适当的多线程。
注意 2: 在调用 EndInvoke
之前,我考虑过在 Finally
中执行以下操作:
If Not asyncResult.IsCompleted Then asyncResult.AsyncWaitHandle.Close()
...但我不知道这是否真的可以正常工作,或者可能造成什么损害。
【问题讨论】:
您不能安全地中止线程。Thread.Abort()
很危险。
@SLaks:我读过很多关于Thread.Abort()
的危险的文章,所以我的目的是找到最好的替代解决方案。让线程保持锁定显然是最糟糕的选择,也是不可接受的。 DoCommand
是非托管代码,因此当它无法从远程服务器检索响应(从导致问题的任何原因)时,我没有选项让它自行中止。这是让我首先将 DoCommand
调用包装到异步委托中的部分原因。还有哪些其他选择?
真的没有。
我不明白,它是一个测试框架。您是否试图在地垫下隐藏测试失败?在测试中担心泄漏有什么意义?
@HansPassant 这并不是真正的测试失败。它发生的时间我可以看到故障发生在 Selenium dll 或 Selenium RC 服务器中。无论哪种方式,问题出在我无法管理的代码中。我的代码需要能够从失败中恢复,将测试标记为失败,然后继续测试。如果要这样做,那么我可以重新运行任何受此异常故障影响的测试并继续前进。
【参考方案1】:
无法同时进行以下操作:
以非合作方式中止/终止线程 不破坏与其关联的所有状态(AppDomain/进程)暗示:要么合作终止(这里不可能)要么终止进程(AppDomain 不够,因为涉及本机状态)或者不终止线程。
你不能杀死线程并让它挂在那里。程序的其余部分(剩余的测试)可以继续执行。
我不乐意在生产环境中看到这一点,但对于测试套件来说,这可能没问题(假设无法修复挂起)。
为什么不能中止线程?这已经在 Stack Overflow 上讨论过很多次了。
【讨论】:
以上是关于.Net 异步委托中止的主要内容,如果未能解决你的问题,请参考以下文章
那些年我们一起追逐的多线程(ThreadThreadPool委托异步调用Task/TaskFactoryParallerlasync和await)