关键终结器中的线程相关性

本文关键字:线程 相关性 | 更新日期: 2023-09-27 18:27:34

我们正在使用一个第三方遗留系统,该系统需要对一些拆卸逻辑进行线程亲和。我们还在IIS中托管WCF服务,在负载过重的情况下,该服务将对我们的应用程序域进行粗鲁的卸载。在这些情况下,关键终结器需要进行清理。不幸的是,如果终结器中没有线程亲和性,第三方系统就会死锁。

大致来说:

public class FooEnvironment : CriticalFinalizerObject, IDisposable
{
  public FooEnvironment()
  {
    // start up C API
  }
  public bool Dispose()
  {
    // shutdown C API (from same thread ctor was called on)
  }
  ~FooEnvironment()
  {
    // try to shutdown C API but deadlock!
  }
}

我已经尝试过从初始化线程使用ExecutionContext运行的各种方法,但这不起作用(至少在IIS中是这样),并且我们得到了一个无效的操作异常,声明不能使用此执行上下文(表面上是因为它可能在AppDomains之间被破坏了,这似乎很可能)。

我读过几篇文章,基本上说我想做的事情是做不到的,但我想我会问,因为关于这个话题的信息不多。

关键终结器中的线程相关性

在过去,我开发了一个库,它封装了丑陋的DDEML,这是一个围绕DDE协议的Win32 api封装器。DDEML也有线程亲和性要求,所以我感觉到你的痛苦。

唯一可行的策略是创建一个专用线程来执行所有库调用。这意味着咬紧牙关,将调用此API的每个请求封送到此专用线程上,然后将结果封送回原始线程。它很糟糕,速度很慢,但它是唯一能保证工作的方法。

这是可以做到的,但很痛苦。你可以在我的NDde库中看到我是如何解决这个问题的。基本上,终结器只需通过静态方法调用将消息发布到线程,该线程可以接受并将消息分派到适当的API调用。在我的例子中,我创建了一个名为Application.Run的线程来侦听消息,因为DDE无论如何都需要Windows消息循环。在您的情况下,您将希望以监视自定义消息队列的方式创建线程。如果使用BlockingCollection类,这并不十分困难,因为Take方法会阻塞,直到队列中出现项目为止。