简体   繁体   中英

TaskScheduler to always run on the same thread

I have some code using a ReaderWriterLockSlim. I acquire a write lock on it when a certain object is constructed, and release it when that object is disposed some time later. However, because of where those calls are coming from, I can't guarantee that they'll be on the same thread, which is a requirement of the ReaderWriterLockSlim.

I believe a reasonable solution would be to run the construction and disposal of the object on a dedicated thread, and have the calling code wait for that task to complete (but keep the thread alive). It seems messy, but I can't think of another approach without massively restructuring our code.

Is there an existing TaskScheduler subclass that will allow me to run two tasks on the same thread?

I am of course open to another paradigm of doing this.

I had a similar problem, so I hope that my solution is going to help you too.

Basically, the problem is that ReaderWriterLockSlim has thread affinity, meaning that thread that acquired a lock is the only one that can release it.

Solution to this is to create one more dedicated thread, but opposed to what you suggested, this thread is going to be dedicated to acquiring and releasing a lock.

I guess that your code looks something like this:

public class ClassUsingReaderWriterLockSlim
{
    private ReaderWriterLockSlim rwsLock;

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

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

And a code that solves your problem will look like this:

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");
    }
}

Well, for you production code you would make this a little differently but the basic idea is to have dedicated thread that is going to do locking and unlocking, and in this way it won't be important from which thread call comes to the methods that are supposed to lock and unlock code/resources...

Hope this helps you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM