关键终结器中的线程亲和力

时间:2012-03-13 15:00:58

标签: c# multithreading iis finalizer

我们正在使用第三方遗留系统,该系统需要与某些拆除逻辑的线程关联。我们还在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上进行了编组,这似乎很可能。)

我已经阅读了几个基本上说明我正在尝试做的事情无法完成的事情,但我想我会问,因为关于这个话题没有太多的信息。

1 个答案:

答案 0 :(得分:1)

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

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

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

相关问题