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");
}
}
Что ж, для вашего производственного кода вы бы сделали это немного по-другому, но основная идея состоит в том, чтобы иметь выделенный поток, который будет выполнять блокировку и разблокировку, и таким образом не будет иметь значения, из какого вызова потока поступают методы, которые должны блокировать и разблокировать код / ресурсы...
Надеюсь, это поможет вам.