我如何强制自己超时?

发布于 2024-07-13 14:59:35 字数 485 浏览 10 评论 0原文

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

string response = theAPI.FunctionA(a, b, c, d);

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

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

I have to use an API to make a call to a third party, and ideally use the response it returns. The API has a built-in 30 second timeout, and does not allow you to set that programatically. I need it to time out in 12 seconds. Here's the call I'm making:

string response = theAPI.FunctionA(a, b, c, d);

I've been thinking I might need to use async calls to accomplish this and abort the thread at 12 seconds. Another stackoverflow question appears to come close to what I'm considering: Implement C# Generic Timeout

...I'm just wondering if this is the best way. Specifically, I keep seeing articles that warn you to call EndInvoke no matter what, and I'm wondering if Abort as in the referenced example will still close the thread appropriately? I see there were some comments with much concern about using Abort.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

携余温的黄昏 2024-07-20 14:59:35

中止线程通常是一个坏主意。 如果调用时间超过 12 秒,为什么不直接让调用完成(或在 30 秒后超时)而忽略结果(并继续)?

Aborting threads is generally a bad idea. Why not just let the call complete (or time out after 30 seconds) but ignore the result (and move on) if it takes more than 12 seconds?

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

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

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

此方法不让受害者有机会进行清理:

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

正如 MSDN 中所述:

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

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

Thread.Abort will close the thread, of course, as it will call Win32 TerminateThread.

Outcome of this action will depend on how your API likes to be closed by TerminateThread.

If your method is called somthing like NuclearPlant.MoveRod() or Defibrillator.Shock(), I'd rather wait these 30 seconds.

This method gives no chance to the victim to do some cleanup:

TerminateThread is used to cause a thread to exit. When this occurs, the target thread has no chance to execute any user-mode code. DLLs attached to the thread are not notified that the thread is terminating. The system frees the thread's initial stack.

As stated in MSDN:

TerminateThread is a dangerous function that should only be used in the most extreme cases. You should call TerminateThread only if you know exactly what the target thread is doing, and you control all of the code that the target thread could possibly be running at the time of the termination. For example, TerminateThread can result in the following problems:

  • If the target thread owns a critical section, the critical section will not be released.
  • If the target thread is allocating memory from the heap, the heap lock will not be released.
  • If the target thread is executing certain kernel32 calls when it is terminated, the kernel32 state for the thread's process could be inconsistent.
  • If the target thread is manipulating the global state of a shared DLL, the state of the DLL could be destroyed, affecting other users of the DLL.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文