如何在线程之间传输锁?

问题描述:

我想如何在线程之间传输锁?

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

但它不工作,因为它不能Monitor.Exit的对象,这不是在当前线程Monitor.Enter上。怎么做?我应该使用线程间通信吗?

+8

你可能做错了什么。这是什么用例? – 2012-02-08 21:37:40

+0

为什么不把'Monitor.Enter'放在工作项目内? – Yahia 2012-02-08 21:39:37

+3

是否有你无法锁定queueUserWorkItem委托内的对象的原因? (您可以锁定然后解锁项目,以便/ *做某些事情* /如果需要排队该项目之前发生的事情。) – Servy 2012-02-08 21:40:09

Semaphore s允许您将它们锁定在一个线程中并在另一个线程中解锁它们。

但是这种行为对我来说是非常可疑的......你究竟在做什么?这在实践中几乎不应该做。

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; 
    } 
} 
+0

我想过使用'SemaphoreSlim',但它是专为短暂的等待期 – 2012-02-09 12:06:52

您可以为此使用Mutexes。它们就像锁,但具有更多的功能。他们也更昂贵。

正如你一定已经知道,你在这里是危险的领土。跨线程传递锁定是危险的...

如何在线程之间转移锁吗?

你在初始线程上输入显示器,比如线程Alpha。尝试进入显示器的任何其他线程都会阻塞,直到显示器可用。

然后,如果您想锁转移到另一个线程,说线程布拉沃,同时仍然能够恢复线程阿尔法与显示器时布拉沃做的所有权,然后你把阿尔法在等待状态在显示器上。如果线程布拉沃是阻止在监视器上然后醒来,进入监视器。当它完成时,它会丢弃显示器,它放弃了Bravo对显示器的所有权,并将所有权转移回Alpha,后者醒来并继续以显示器的所有权运行。 (1)你不应该试图在第一时间做到这一点;但是,如果你完全不清楚这一点,

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

如果埃里克Lipert的回答适合我,我会实现:如果你弄错了,和(2)你应该阅读这是超级危险的

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

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

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

不幸的是这个解决方案没有按”防止另一个线程锁定this.StaticLock Monitor.Wait和队列之间的线程锁

一种替代方法是使用WaitHandle

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

     } 
     finally 
     { 
      waitHandle.Set(); 
     } 

     // Do something else... 

    } 
} 

waitHandle.WaitOne();