超时后中止卡住的方法

Posted

技术标签:

【中文标题】超时后中止卡住的方法【英文标题】:Aborting a stuck method after a timeout 【发布时间】:2017-09-27 10:34:29 【问题描述】:

我们的程序正在执行来自 DLL 的未知方法。有时这些方法不会处理超时并且永远不会返回值。

因此,我们的 Methodinfo.invoke(...) 将永远停留在这一行。

有什么体面的方法可以中止我们的方法吗? 我知道我可能应该异步运行这个方法,这没问题。

这里有一些可视化的小例子:

 public string startTheDLLMethod(int timeout)
    
        var methodinfo = "...";

        return methodGettingStuck(methodinfo); //todo, abort this after timeout
    

    public string methodGettingStuck(methodinfo)
    
        var1 = "";
        var2 = "";

        methodinfo.Invoke(var1, var2); //Stuck.
    

【问题讨论】:

ThreadAbortException?请提供minimal reproducible example。 阅读更多关于CancellationTokenSource的信息。 您是否声称 CancellationTokenSource 能够在该方法卡在 1 行时停止该方法 DLL 分配的东西难吗?当 DLL 分配 FileHandles 或类似的东西时,我不建议使用 Thread.Abort 和 ThreadAbortException。 我不知道未来不同公司的 DLL 会做什么,所以也许 【参考方案1】:

正如评论中所建议的,如果在 dll 中分配了文件句柄之类的东西,我会尝试不使用 ThreadAbortException

但是给你:

    public void BlockingCallWithTimeout()
    
        Semaphore waitHandle = new Semaphore(0,1);
        Thread thread = new Thread(this.Wrapper);
        Timer timer = new Timer(state =>
        
            thread.Abort();
            waitHandle.Release();
        ,null,5000,0);

        thread.Start(waitHandle);

        waitHandle.WaitOne(); //wait until completion or until timeout
        timer.Dispose();
    

    public void Wrapper(object state)
    
        Semaphore semaphore = (Semaphore)state;

        //Call DLL Method

        semaphore.Release();
    

您需要在代码中的某处处理 ThreadAbortException(没有尝试过)。这段代码只是一个例子!您需要注意同时发生超时和成功的情况。所以 Timer 不会在它执行的那一刻被释放 - 并且可能有更多的竞争条件需要处理。

【讨论】:

它带来了一些困难,因为该方法需要返回一个字符串,并接受多个对象和变量作为参数,但我解决了这个问题。该解决方案有效,如果线程处于中间状态,中止线程可能会导致问题,但至少我现在可以告诉用户这不是我的程序,而是坏的 DLL,这是一个目标。谢谢 更新:如果该方法正在使用 COM 端口之类的资源,并且您中止线程,则会导致“安全句柄已关闭”错误和程序崩溃。但是我也设法通过在不同的应用程序域中执行线程来解决这个问题。 ***.com/questions/46562227/…

以上是关于超时后中止卡住的方法的主要内容,如果未能解决你的问题,请参考以下文章

易语言外部判断程序超时防卡住

HttpWebRequest.GetResponse 方法卡住特定的 url

Vagrant卡住连接超时重试

读取带有 rvest 的 HTML 表有时会卡住并产生超时错误

PHP-FPM 进程突然卡住

python requests请求卡住问题