2011-08-14 161 views
2

我想找到在多个类之间共享锁文件的最佳做法。在此之前,我在同一个类中放置了多个函数,因此他们可以共享一个相互锁文件和一个生产者/消费者队列。代码比我想要的要长,我想把它们分解成单独的类。当我这样做时,我无法共享锁定文件或者添加/删除命令的队列。锁类之间的共享

我需要一个接受用户输入的UI线程,然后将这些命令放入工作线程可以从中拉出的锁定队列中。我想将UI线程和工作者函数放到不同的类中,以保持我的代码组织良好。

对不起,如果这太模糊。有没有办法做到这一点,不会破坏好的设计技巧?

回答

2

如果这些锁在多个类之间共享,并且“所有者”不易识别,请将这些锁放入共享的类中。

public class MyLocks { ... all your locks ... } 

然后,当你初始化你的类使用锁,将它们传递给构造函数。或者,您可以让这些类自己实例化MyLocks,然后将其作为一个属性公开,然后在随后的构建中使用它。

... 
var a = new ClassWithLocks(); 
var b = new ClassWithLocks(a.MyLocks); 
var b = new SomeOtherClassWithLocks(a.MyLocks); 
... 

外卖是将锁放入自己的单位。

更新

放置多个锁进自己的阶级的另外一个好处是,你可以明确地创建抓住和释放锁的方法。例如:

void PushLock(string myToken, LOCK_ENUM theLockIWant); 
void PopLock(string myToken, LOCK_ENUM theLockIWant); 

现在某一类或操作可以请求锁,但如果他们试图抓住一个锁,其枚举低于他们所请求的锁,你可以抛出一个异常。当您需要多个锁执行操作时,这一点很重要,因为您可以确保按顺序获取并释放这些锁,这是死锁中最常见的罪魁祸首之一。

+0

这就是我正在考虑使用的内容,但是读到以这种方式传递锁定文件并不是很好的设计..我认为,对于唯一被锁定的项目是一个工作队列,尽管如此,问题仍然很多。 – mlapaglia

+1

如果两个类紧密结合,以至于他们知道对方的锁,那么它们就可以有效地作为单个可测试单元进行操作。有一些技巧可以通过接口和嵌套类来隐藏公共锁的实现,但这可能是矫枉过正的。实际上,我通过创建一个WorkItem(我将其提交给一个队列)来减少所需的锁的数量。该队列由一个线程使用,该线程在轮到他时调用提交者,并且避免了回调函数捕获所有锁的需要。当然,这一切都取决于你在做什么。 –

1

你可以使用从System.Collection.Concurrent命名空间中的线程安全ConcurrentQueue和您的UI线程和工作线程像这样之间共享该队列:

ConcurrentQueue<T> workItems = new ConcurrentQueue<T>(); 

UIThreadClass uiThread = new UIThreadClass(workItems); 

WorkerThreadClass workerThread = new WorkerThread(workItems); 

uiThread.Run(); 

workerThread.Run(); 

在您的工作线程类,你可以定期检查通过使用TryPeek()方法的新项目的工作项目队列 。有关 ConcurrentQueue的详细说明,请参阅MSDN

希望,这有助于。

0

什么是'锁定文件'?你使用FileStream Lock/Unlock方法吗?如果是这样,你可能会考虑你是否真的需要它们。

回到锁定:我认为一个简单的,共享的,ReaderWriterLockSlim)应该在大多数情况下(和你的)。 Michael概述了基本思想 - 您应该在其上添加一个singleton - 这将简化您的项目和生活(无需传递实例,更易于调试)。

注意那些线程,死锁不好玩!

PS:这可能很明显(对某些人),但锁只在处理多个线程时才有效。

+0

对不起,我的意思是锁定变量,如 只读对象workLock = new object(); – mlapaglia

+0

谢谢。看到你对死锁的评论,提醒我一个集中的类允许在排除锁故障时更加慎重 - 特别是允许一个人按顺序获取锁,并且只能按照该顺序释放。 –