TaskScheduler всегда запускается в одном потоке

У меня есть код, использующий ReaderWriterLockSlim. Я получаю блокировку записи, когда создается определенный объект, и освобождаю его, когда этот объект удаляется через некоторое время. Однако из-за того, откуда поступают эти вызовы, я не могу гарантировать, что они будут в одном потоке, что является требованием ReaderWriterLockSlim.

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

Существует ли существующий подкласс TaskScheduler, который позволит мне запускать две задачи в одном потоке?

Я, конечно, открыт для другой парадигмы этого.

1 ответ

У меня была похожая проблема, поэтому я надеюсь, что мое решение тоже поможет вам.

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

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

Я думаю, что ваш код выглядит примерно так:

public class ClassUsingReaderWriterLockSlim
{
    private ReaderWriterLockSlim rwsLock;

    public void MethodThatAcquiresLock()
    {
        rwsLock.EnterWriteLock();
    }

    public void MethodThatReleasesLock()
    {
        rwsLock.ExitWriteLock();
    }
}

И код, который решает вашу проблему, будет выглядеть так:

public class ClassUsingReaderWriterLockSlim
{
    private ReaderWriterLockSlim rwsLock;
    Thread dedicatedThreadForReaderWriterLockSlim;
    Queue<string> commandsForDedicatedThread;

    public ClassUsingReaderWriterLockSlim()
    {
        commandsForDedicatedThread = new Queue<string>();
        dedicatedThreadForReaderWriterLockSlim = new Thread(ThreadFunction);
        dedicatedThreadForReaderWriterLockSlim.Start();
    }

    private void ThreadFunction(object obj)
    {
        while (!terminatingCondition)
        {
            // Wait until something is in queue...

            if (commandsForDedicatedThread.Count > 0)
            {
                switch (commandsForDedicatedThread.Dequeue())
                {
                    case "ENTER LOCK":
                        rwsLock.EnterWriteLock();
                    case "EXIT LOCK":
                        rwsLock.EnterWriteLock();
                    default:
                    // Do nothing...
                }
            }
        }
    }

    public void MethodThatAcquiresLock()
    {
        commandsForDedicatedThread.Enqueue("ENTER LOCK");
    }

    public void MethodThatReleasesLock()
    {
        commandsForDedicatedThread.Enqueue("EXIT LOCK");
    }
}

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

Надеюсь, это поможет вам.

Другие вопросы по тегам