C# 关键终结器中的线程关联

C# 关键终结器中的线程关联,c#,multithreading,iis,finalizer,C#,Multithreading,Iis,Finalizer,我们正在使用一个第三方遗留系统,该系统要求某些拆卸逻辑具有线程亲和力。我们还在IIS中托管一个WCF服务,在重载情况下,它会对我们的应用程序域进行粗鲁的卸载。在这些情况下,由关键终结器进行清理。不幸的是,如果终结器中没有线程关联,第三方系统就会死锁 大致来说: public class FooEnvironment : CriticalFinalizerObject, IDisposable { public FooEnvironment() { // start up C AP

我们正在使用一个第三方遗留系统,该系统要求某些拆卸逻辑具有线程亲和力。我们还在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进行了marashalled,这似乎是可能的)


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

早在过去,我开发了一个库,它包装了可怕的DDEML,这是一个围绕DDE协议的Win32 api包装器。DDEML也有线程亲和力要求,所以我感觉到了您的痛苦

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


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

我遇到了这个问题,如果线程与我期望的不匹配,我不得不放弃进行任何清理。这当然不理想。释放了什么资源?你能不能不释放它?它不是任何特定的资源,而是线程级别的分配,这些分配是在(不是很好的)第三方系统中以每个线程为基础完成的。系统似乎使用线程标识来分配和释放这些资源,而且似乎没有任何方法可以绕过这种行为。