Заставить WCF использовать один поток

У меня есть консольное приложение, которое использует внешнюю библиотеку. Библиотеканастаивает на том, всегда вызываться из одного и того же потока; иначе он запирает. (Я попытался запустить как STA, чтобы увидеть, исправит ли это, но нет, это действительнонастаивает на том, Вы должны всегда использовать одну и ту же нить. Я думаю, что поток локального хранилища ...)

Ранее приложение связывалось с использованием необработанного TCP-соединения. Тем не менее, я недавно изменил его, чтобы использовать WCF. Теперь кажется, что WCF случайным образом выбирает потоки для запуска моего кода, что приводит к впечатляющей ошибке.

Мне нужно абсолютно 100%предотвращать это поведение никогда не происходит. Мне все равнокоторый поток мой код работает, пока он всегдатот же самый нить! Я провел последние несколько дней, обыскивая лицо Интернета и неоднократно ломая голову в клавиатуру в отчаянной попытке заставить WCF прекратить использовать потоки.

Вещи, которые я пробовал:

InstanceContextMode.Single заставляет WCF использовать одинобъект для моих вещей, которые полезны, но не решают проблему напрямую.

ConcurrencyMode = ConcurrencyMode.Single гарантирует, что одновременно будет работать только один поток, но не обещаеткоторый из.

UseSynchronizationContext Кажется, что ни на что не влияет, насколько я могу судить.

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

Я также попробовал подход грубой силы: я написал класс, который создает собственный рабочий поток и позволяет ставить код в очередь для выполнения в этом потоке. Я тестировал класс изолированно, и он, кажется, отлично работает, но когда я пытаюсь использовать его в своем приложении WCF, происходит что-то чрезвычайно странное. Программа обрабатываетпервый Команда отлично, возвращает результат клиенту, а затем зависает навсегда.

Такое поведение не имеет абсолютно никакого смысла. Я могувидеть из вывода консоли, что он не застрял во внешней библиотеке, и он не застрял в моем новом классе организации очередей. Так где, черт возьми, он застрял ?!

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

Я видел разные ответы SO на эту тему, все из которых говорят, что решение - это нечто совершенно другое. Есть один, который говорит о «контекстах синхронизации» и является более или менее непонятным - но, похоже, он будет делать то же самое, что и мой класс рабочей очереди. Есть еще один способ установки различных служебных флагов - что я уже сделал, и это не помогло. Кто-то еще предложил реализовать свой собственныйIOperationBehaviour (который выглядит безумно сложным).

По сути, на данный момент я не уверен, что, черт возьми, делать, и я не могу заставить этот материал работать. Пожалуйста, помогите. :-(

[Консольное приложение, самостоятельно размещенное,NetTcpBinding, конфигурация в коде .NET 4 - в случае, если это имеет значение ...]

Вот класс рабочей очереди, если он имеет значение: [Это немногобольшойКСТАТИ.]

public sealed class ThreadManager
{
    private Thread _thread; // Worker thread.
    private volatile Action _action; // Enqueued method.
    private volatile object _result; // Method result.
    private volatile bool _done; // Has the method finished executing?

    public void Start()
    {
        _action = null;
        _result = null;
        _done = true;
        _thread = new Thread(MainLoop);
        _thread.Start();
    }

    public void ExecuteInWorkerThread(Action action)
    {
        // Wait for queue to empty...

        Monitor.Enter(this); // Lock the object, so we can inspect it.

        while (_action != null)
        {
            Monitor.Pulse(this); // Wake up the next thread waiting on the lock.
            Monitor.Wait(this); // Release lock, wait for Pulse(), acquire lock.
        }

        // Enqueue action...

        _action = action;
        _done = false;

        // Wait for action to complete...

        while (! _done)
        {
            Monitor.Pulse(this); // Wake up the next thread waiting on the lock.
            Monitor.Wait(this); // Release lock, wait for Pulse(), acquire lock.
        }

        // Worker thread has finished doing it's thing now.

        Monitor.Pulse(this); // Wake up any threads trying to enqueue work.
        Monitor.Exit(this); // Release the lock.
    }

    public T ExecuteInWorkerThread<T>(Func<T> action)
    {
        ExecuteInWorkerThread(() => { _result = action(); });
        return (T) _result; // If this cast fails, something has gone spectacularly wrong!
    }

    // Runs forever in worker thread.
    private void MainLoop()
    {
        while (true)
        {
            // Wait for an action to dequeue...

            Monitor.Enter(this); // Lock object so we can inspect it.

            while (_action == null)
            {
                Monitor.Pulse(this); // Wake up the next thread waiting on the lock.
                Monitor.Wait(this); // Release lock, wait for Pulse(), acquire lock.
            }

            // Dequeue action...

            var action = _action;
            _action = null;

            // Perform the action...

            action(); // Do the actual action!

            _done = true; // Tell the caller we're done.

            Monitor.Pulse(this); // Wake the caller up.
            Monitor.Exit(this); // Release the lock.
        }
    }
}

Как я уже сказал, когда я тестирую это изолированно, кажется, что оно работает нормально. [Что-то бормочет о многопоточном кодировании и детерминизме.] При запуске в WCF всегда происходит сбой в одной и той же точке.

Ответы на вопрос(3)

Ваш ответ на вопрос