Сходство потоков в критическом финализаторе - PullRequest
3 голосов
/ 13 марта 2012

Мы работаем со сторонней унаследованной системой, которая требует схожести потоков для некоторой логики разрыва. Мы также размещаем службу WCF внутри IIS, которая при больших нагрузках будет выполнять грубую разгрузку нашего домена приложения. В этих случаях ответственному финализатору приходится выполнять очистку. К сожалению, без привязки потоков в финализаторе сторонние системы блокируются.

Так примерно:

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), и мы получаем недопустимое исключение операции, заявляющее, что этот контекст выполнения не может быть использован ( якобы потому, что он мог быть перераспределен по доменам приложений, что кажется вероятным).

Я прочитал несколько вещей, в основном утверждая, что то, что я пытаюсь сделать, не может быть сделано, но я решил спросить, так как по этой теме не так много информации.

1 Ответ

1 голос
/ 13 марта 2012

В прежние времена я разработал библиотеку, которая обернула отвратительный DDEML, который является оболочкой API Win32, вокруг протокола DDE.У DDEML также есть требования к соприкосновению потоков, поэтому я чувствую вашу боль.

Единственная стратегия, которая будет работать, - это создать отдельный поток, который будет выполнять все ваших вызовов библиотеки.Это означает, что нужно перебрать маркер и выполнить маршалинг каждого отдельного запроса для вызова этого API в этом выделенном потоке, а затем перенаправить результат в исходный поток.Это отстой и медленный, но это единственный гарантированный метод.

Это можно сделать, но это больно.Вы можете увидеть, как я решил эту проблему в моей библиотеке NDde .По сути, финализатор просто отправляет сообщение с помощью статических вызовов методов в поток, который может принять и отправить их в соответствующий вызов API.В моем случае я создал поток, который вызывал Application.Run для прослушивания сообщений, потому что DDE все равно требовал цикл сообщений Windows.В вашем случае вы захотите создать поток так, чтобы он отслеживал пользовательскую очередь сообщений.Это не очень сложно, если вы используете класс BlockingCollection, потому что метод Take блокируется, пока элемент не появится в очереди.

...