【问题标题】:What happens if an asynchronous delegate call never returns?如果异步委托调用永远不会返回会发生什么?
【发布时间】:2011-03-01 05:50:40
【问题描述】:

我找到了一个不错的示例,说明如何使用超时异步调用委托...http://www.eggheadcafe.com/tutorials/aspnet/847c94bf-4b8d-4a66-9ae5-5b61f049019f/basics-make-any-method-c.aspx。总之,它使用带有超时的 WaitOne 来确定调用是否在超时到期之前没有返回。

我也知道你应该有一个 EndInvoke 来匹配每个 BeginInvoke。

那么如果等待超时到期会发生什么?我们(大概)不想调用 EndInvoke,因为那会阻塞。代码可以继续做“其他事情”,但我们泄露了什么吗?是否有一些糟糕的线程被阻塞在等待永远不会发生的返回?我们是否泄漏了一些内存,该结果将永远不会返回?

【问题讨论】:

    标签: c# .net asynchronous timeout delegates


    【解决方案1】:

    我觉得this这个帖子讲的很好:

    来自帖子:

    如果它不是您的线程,您不能终止正在执行的异步委托,但如果是,您可以。如果您使用常见的 BeginInvoke 类型方法,您将获得一个由框架管理的线程池线程。如果您使用 Thread() 类,您将拥有自己的线程来管理、启动、暂停等。

    异步开发需要一个人决定谁来管理线程。许多不同的异步执行方法都在后台使用 ThreadPool 线程。

    由于您不能/不应该终止线程池线程,因此您必须设计代码以与线程通信,以便它可以退出。 BackgroundWorker 组件的 MSDN 示例演示了这种通信。

    有时您的代码可能有线程阻塞等待 IO。在这里,您通常会使用多对象等待,等待 IO 或 ManualResetEvent。

    因此,简而言之,如果存在超时的可能性并且您希望线程结束,您需要自己找到一种方法来管理线程。

    【讨论】:

      【解决方案2】:

      你需要调用 EndInvoke()。

      这是一个讨论 EndInvoke() 发生了什么的链接:

      Is EndInvoke() optional, sort-of optional, or definitely not optional?

      这是已接受答案中文章的link

      我们一直在各种公共论坛上讨论异步委托调用的“即发即弃”技术。许多 DevelopMentor 讲师撰写了展示该技术的文章和示例代码,我们都在课堂上进行了描述。当然,当时它也在唐的书中。所以当微软最终记得要让外界知道这种技术实际上并不合法时,真是令人震惊。

      关于异步模式的 MSDN link

      【讨论】:

        【解决方案3】:

        你会泄露线程持有的资源。会有各种各样的 .NET 远程处理管道对象,例如 AsyncResult。与线程关联的几个非托管句柄。与您将泄漏的由线程堆栈保持的 1 兆字节的虚拟内存地址空间相比,所有这些都是小菜一碟。

        您不能以任何方式中止线程,泄漏是永久性的。当您必须处理此类行为不良的代码时,您唯一的好资源就是在单独的进程中运行它,这样当您使用 Process.Kill() 对进程进行头部处理时,您可以让 Windows 清理弹片。即使不能保证,这种冻结往往与行为不端的设备驱动程序有关。 Process.Kill 不会终止设备驱动程序线程。很容易看到:尝试使用 Taskmgr.exe 中止进程将使其仅使用一个句柄运行。如果这没有发生,你还有一些希望。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-05-25
          • 2021-09-19
          • 1970-01-01
          • 2017-07-13
          • 2016-01-16
          • 2016-10-31
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多