Skip to main content
 首页 » 编程设计

c#之给对象一个成员对象的独占锁

2024年01月02日33softidea

我的网络应用程序中的每个请求都可以通过 MVC3 自己的依赖注入(inject)机制获得一个数据访问对象实例(类型为 UnitofWork)。到目前为止一切顺利。

我正在创建一个 Idisposable UnitofWorkScope 对象来聚合对此数据访问对象的一些存储调用,然后将它们一起调用。实际上,UnitofWorkScope 仅控制 UnitofWork 对象,该对象具有将商店添加到列表并稍后调用它们的功能。我相信 UnitofWorkScope 对象应该对数据访问对象具有独占访问权限。

现在的问题是:我想知道是否有人反对在构造函数中使用 Monitor.Enter() 获得独占锁,然后在处置方法中使用 Monitor.Exit 释放排他锁();

我通过描述我问这个问题的原因来混淆水域,但请随意评论我放在这里的任何内容。

public class UnitofWorkScope : IDisposable 
{ 
    public UnitofWorkScope(UnitOfWork UnitofWork) 
    { 
        if (UnitofWork == null) 
        { 
            throw new ArgumentException("UnitofWork argument null"); 
        }   
        this._unitofWork = UnitofWork; 
        Monitor.Enter(_unitofWork); // obtaining exclusive access to the DAO of this request 
        this._unitofWork.AggregateDbChanges = true; //switched back off in dispose method 
    } 
 
    private readonly UnitOfWork _unitofWork; 
 
    bool _disposed; 
 
    public void Dispose(bool disposing) 
    { 
        if (!_disposed) 
        { 
            _unitofWork.CallFuncList(); 
            Monitor.Exit(_unitofWork); //releasing the lock 
            _disposed = true; 
            GC.SuppressFinalize(this); 
        } 
    } 
 
    public void Dispose() 
    { 
        Dispose(true); 
    } 
 
    ~UnitofWorkScope() 
    { 
        if (!_disposed) 
        { 
            Dispose(false); 
        } 
    } 
} 

想法是像这样使用这个 UnitofWorkScope:

UnitofWork _unitofWork = Resolver.GetService<UnitofWork>(); //gets the UnitofWork DAO 
 
using (UnitofWorkScope UnitofWorkScope = new UnitofWorkScope(_unitOfWork)) 
{ 
    // do a store 
 
    _unitofWork.Store<SomeClass>(_someInstance); 
 
   // do some more stores  
 
   try 
   { 
        UnitofWorkScope.Dispose(true);  
   } 
   catch (exception ex) 
   { 
     //try to undo those stores. 
   } 
}  

请您参考如下方法:

是的,这不是实现锁的坏模式。但是:我建议使用稍微不同的 Dispose 版本,以保证即使 _unitofWork.CallFuncList() 抛出异常也能释放锁,您依靠它来检测是否需要执行某种回滚.

private void Dispose(bool disposing)  
{  
    if (!_disposed)  
    {  
        try 
        { 
            _disposed = true;  
            _unitofWork.CallFuncList();  
        } 
        finally 
        { 
            Monitor.Exit(_unitofWork); //releasing the lock  
            GC.SuppressFinalize(this);  
        } 
    }  
}  

但是,您可能希望将“提交”与锁定“释放”逻辑分开,这样您就不必显式调用 Dispose(),using 语句会自动执行此操作给你。

public void Commit() 
{ 
    _unitofWork.CallFuncList();  
} 
 
private void Dispose(bool disposing)  
{  
    if (!_disposed)  
    {  
        try 
        { 
            _disposed = true;  
        } 
        finally 
        { 
            Monitor.Exit(_unitofWork); //releasing the lock  
            GC.SuppressFinalize(this);  
        } 
    }  
} 

然后你可以像这样使用它:

using (var unitofWorkScope = new UnitofWorkScope(_unitOfWork))      
{      
    // do a store      
 
    _unitofWork.Store<SomeClass>(_someInstance);      
 
   // do some more stores       
 
   try      
   {      
        unitofWorkScope.Commit(); 
   }      
   catch (exception ex)      
   {      
     //try to undo those stores.      
   }      
}  // unitofWorkScope.Dispose() automatically called here