How to transfer locks between threads?

让人想犯罪 __ 提交于 2019-12-05 07:21:19

问题


I would like to

Monitor.Enter(this.StaticLock);
try
{
    // Do something ...

    ThreadPool.QueueUserWorkItem(state =>
    {
        try
        {
             // Do something else...

        }
        finally
        {
            Monitor.Exit(this.StaticLock);
        }
    });
}
catch (Exception)
{
    Monitor.Exit(this.StaticLock);
    throw;
}

But it doesn't work since the it can't Monitor.Exit on an object that wasn't Monitor.Enter in the current thread. How to do that? Should I use interthread communication?


回答1:


Semaphores allow you to lock them in one thread and unlock them in another.

But this kind of behavior is very suspicious to me... What exactly are you trying to accomplish? This should almost never be done in practice.

static readonly Semaphore semaphore = new Semaphore(1, 1);

void Method1()
{
    semaphore.WaitOne();
    try
    {
        // Do something ...

        new Thread(() =>
        {
            try
            {
                // Do something else...

            }
            finally
            {
                semaphore.Release();
            }
        }).Start();
    }
    catch (Exception)
    {
        semaphore.Release();
        throw;
    }
}



回答2:


How to transfer locks between threads?

You enter the monitor on the initial thread, say thread Alpha. Any other threads that try to enter the monitor will block until the monitor is available.

If you then want to transfer the lock to another thread, say thread Bravo, while still being able to resume thread Alpha with ownership of the monitor when Bravo is done, then you put Alpha in a wait state on the monitor. If thread Bravo is blocked on the monitor then it wakes up and enters the monitor. When it is done it pulses the monitor, which abandons Bravo's ownership of the monitor and transfers ownership back to Alpha, which wakes up and keeps on running with its ownership of the monitor.

If that is totally not clear to you then (1) you shouldn't be trying to do this in the first place; this is super dangerous if you get it wrong, and (2) you should read this:

http://www.codeproject.com/Articles/28785/Thread-synchronization-Wait-and-Pulse-demystified




回答3:


You can use Mutexes for this. They are like locks but with a little more features. They are also more expensive.

As you surely already know, you are in dangerous territory here. Passing locks across threads is dangerous...




回答4:


One alternative is to use a WaitHandle

var waitHandle = new AutoResetEvent(initialState: false);
ThreadPool.QueueUserWorkItem(state =>
{
    lock(this.staticLock)
    {
        try
        {
            // Do something ...

        }
        finally
        {
            waitHandle.Set();
        }

        // Do something else...

    }
}

waitHandle.WaitOne();



回答5:


If Eric Lippert's answer suited me I would implement:

lock(this.StaticLock)
{
    ThreadPool.QueueUserWorkItem(state =>
    {
        lock(this.StaticLock)
        {
             // Do something ...

             Monitor.Pulse(this.StaticLock);
             // Do something else...

        }
    });
    Monitor.Wait(this.StaticLock);
}

Unfortunately this solution doesn't prevent another thread from locking this.StaticLock between the Monitor.Wait and the queued thread lock



来源:https://stackoverflow.com/questions/9201848/how-to-transfer-locks-between-threads

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!