问题
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:
Semaphore
s 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