【问题标题】:How can I impose my own timeout?我怎样才能强加自己的超时?
【发布时间】:2010-10-06 17:00:01
【问题描述】:

我必须使用 API 来调用第三方,并且最好使用它返回的响应。 API 有一个内置的 30 秒超时,并且不允许您以编程方式设置它。我需要它在 12 秒内超时。这是我正在打的电话:

字符串响应 = theAPI.FunctionA(a, b, c, d);

我一直在想我可能需要使用异步调用来完成此操作并在 12 秒时中止线程。另一个 stackoverflow 问题似乎接近我正在考虑的问题:Implement C# Generic Timeout

...我只是想知道这是否是最好的方法。具体来说,我一直看到警告您无论如何都要调用 EndInvoke 的文章,我想知道引用示例中的 Abort 是否仍会适当地关闭线程?我看到有些 cmets 非常担心使用 Abort。

【问题讨论】:

    标签: multithreading timeout abort


    【解决方案1】:

    中止线程通常是个坏主意。为什么不让调用完成(或在 30 秒后超时),而在超过 12 秒的情况下忽略结果(然后继续)?

    【讨论】:

    • 交易时间为 12 秒,我需要退出并继续前进。我不能坐等整整 30 秒。如果允许我让它运行整整 30 秒,我肯定会这样做。
    • 我不是建议等待 30 秒。请注意“如果花费超过 12 秒,则忽略结果(并继续)”位。我只是建议您的超时实际上不应终止请求。让它自然完成,而您可以继续处理其他事情。
    • 好吧,我想我跟着你了。我可能会使用回调函数进行异步调用,等待事情完成。同时,我的代码继续运行,如果 12 秒后我还没有响应,我会继续进行,就好像有超时一样。如果超过 12 秒,我的回调函数什么也不做。
    • 是的,类似的事情 :) 只是一个 BeginInvoke/WaitOne(timeout)/EndInvoke 可能没问题,如果主线程没有调用 EndInvoke 回调。不过,您必须检查是否可以多次调用 EndInvoke - 我不知道。
    【解决方案2】:

    Thread.Abort 当然会关闭线程,因为它会调用 Win32 TerminateThread

    此操作的结果将取决于您的API 喜欢如何被TerminateThread 关闭。

    如果您的方法被称为 NuclearPlant.MoveRod()Defibrillator.Shock() 之类的东西,我宁愿等待这 30 秒。

    这种方法没有让受害者有机会做一些清理工作:

    TerminateThread 用于导致线程退出。发生这种情况时,目标线程没有机会执行任何用户模式代码。附加到线程的 DLL 不会收到线程正在终止的通知。系统释放线程的初始栈。

    MSDN中所述:

    TerminateThread 是一个危险的函数,只能在最极端的情况下使用。只有当您确切知道目标线程在做什么并且您控制了目标线程在终止时可能正在运行的所有代码时,您才应该调用TerminateThread。例如,TerminateThread 可能会导致以下问题:

    • 如果目标线程拥有临界区,则不会释放临界区。
    • 如果目标线程正在从堆中分配内存,则不会释放堆锁。
    • 如果目标线程在终止时正在执行某些 kernel32 调用,则线程进程的 kernel32 状态可能不一致。
    • 如果目标线程正在操作共享 DLL 的全局状态,则 DLL 的状态可能会被破坏,从而影响 DLL 的其他用户。

    【讨论】:

    • 听起来你不觉得做 Abort 是一个安全的想法,我可以通过你的 cmets 看出原因。因此,如果要避免中止,您有替代解决方案吗?
    • 如果您的 API 无法停止该方法,则没有替代解决方案。所有这些解决方案(如果有的话)都依赖于线程对外部信号做出反应并采取适当行动的能力。如果线程不这样做,TerminateThread 是停止它的唯一方法。
    猜你喜欢
    • 1970-01-01
    • 2012-01-15
    • 2014-06-22
    • 2013-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-28
    • 2017-01-15
    相关资源
    最近更新 更多