我正在尝试找到在多个类之间共享锁文件的最佳实践。在此之前,我将多个函数放在同一个类中,因此它们可以共享一个相互锁定文件和一个生产者/消费者队列。代码比我想要的要长一些,我想把它们分成几个单独的类。当我这样做时,我无法共享锁文件或队列来添加/删除命令。
我需要一个接受用户输入的UI线程,然后将命令放入工作线程可以从中拉出的锁定队列中。我想将UI线程和worker函数放在不同的类中,以保持我的代码组织良好。
很抱歉,如果这太模糊了。有没有办法做到这一点,不破坏良好的设计技术?
答案 0 :(得分:2)
如果锁在多个类之间共享,并且“owner”不易识别,则将这些锁放入共享的类中。
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);
现在一个特定的类或操作可以请求锁定,但是如果它们试图获取一个锁定,其枚举数小于它们请求的锁定,则可以抛出异常。当您需要多个锁来执行操作时,这很重要,因为您可以确保按顺序获取和释放锁,这是死锁中最常见的罪魁祸首之一。
答案 1 :(得分: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。
希望,这有帮助。
答案 2 :(得分:0)
什么是'锁定文件'?您使用的是FileStream Lock / Unlock方法吗?如果是这样,你可能会考虑是否真的需要它们。
回到锁定:我认为在大多数情况下(和你的),我应该做一个简单的共享ReaderWriterLock(Slim)。迈克尔概述了基本思想 - 你应该在其上添加一个singleton - 它会简化你的项目和生活(不需要传递实例,更容易调试)。
小心那些线程,死锁并不好玩!
PS:对某些人来说可能是显而易见的,但锁只在处理多个线程时才有效。