锁和管理锁异常的分享解决方案有什么问题?我的目标是在我的应用程序中使用线程安全函数和异常处理的约定。我对线程管理/多线程的概念比较陌生。我正在使用.NET3.5阅读这篇文章http://blogs.msdn.com/b/ericlippert/archive/2009/03/06/locks-and-exceptions-do-not-mix我写了以下帮助方法包装所有锁定的操作。aspx,它与这个问题有关,Monitorvslock。我的想法是,如果我在我的应用程序中始终如一地使用这个约定,那么在不破坏状态的情况下,编写线程安全代码和处理线程安全代码中的错误会更容易。publicstaticclassLocking{privatestaticreadonlyDictionaryCorruptionStateDictionary=newDictionary();私有静态只读对象CorruptionLock=newobject();publicstaticboolTryLockedAction(objectlockObject,Actionaction,outExceptionexception){if(IsCorrupt(lockObject)){exception=newLockingException("无法对损坏的对象执行锁定操作。");返回假;}异常=空;Monitor.Enter(lockObject);尝试{action.Invoke();}catch(Exceptionex){exception=ex;}finally{lock(CorruptionLock)//我不想在其损坏状态更新之前释放lockObject。//只要调用类通过TryLockedAction()锁定了lockObject,这应该可以工作{Monitor.Exit(lockObject);if(exception!=null){if(CorruptionStateDictionary.ContainsKey(lockObject)){CorruptionStateDictionary[lockObject]=true;}else{CorruptionStateDictionary.Add(lockObject,true);}}}}返回异常==空;}publicstaticvoidUncorrupt(objectcorruptLockObject){if(IsCorrupt(corruptLockObject)){lock(CorruptionLock){CorruptionStateDictionary[corruptLockObject]=false;}}else{if(!CorruptionStateDictionary.ContainsKey(corruptLockObject)){thrownewLockingException("Uncorrupt()对未损坏的对象无效。");}else{//该对象之前未损坏。//我的想法是忽略调用。}}}publicstaticboolIsCorrupt(objectlockObject){lock(CorruptionLock){returnCorruptionStateDictionary.ContainsKey(lockObject)&&CorruptionStateDictionary[lockObject];}}}我使用LockingException类来简单化测试publicclassLockingException:Exception{publicLockingException(stringmessage):base(message){}}这是一个示例使用类,用于说明我如何计算如何使用它。publicclassExampleUsage{privatereadonlyobjectExampleLock=newobject();publicvoidExecuteLockedMethod(){异常异常;boolvalid=Locking.TryLockedAction(ExampleLock,ExecuteMethod,outexception);if(!valid){boolrevalidated=EnsureValidState();如果(重新验证){Locking.Uncorrupt(ExampleLock);}}}privatevoidExecuteMethod(){//做某事,可能会抛出异常}publicboolEnsureValidState(){//确保状态有效的代码//如果有异常返回false,返回true;}}由于TryLockedAction中的竞争,您的解决方案似乎只是增加了复合性:if(IsCorrupt(lockObject)){exception=newLockingException("Cannotexecutelockedactiononacorruptobject.");返回假;}异常=空;Monitor.Enter(lockObject);if(IsCorrupt(lockObject)){exception=newLockingException("无法对损坏的对象执行锁定操作。");返回假;}异常=空;Monitor.Enter(lockObject);当我们还在等待Monitor.EntelockObject可能在r时“损坏”,因此没有保护我不确定你想要实际发生什么,但可能有助于分离锁和状态管理:classStateManager{publicboolIsCorrupted{get;放;}publicvoidExecute(Actionbody,FuncfixState){if(this.IsCorrupted){//在这里使用一些异常派生类。thrownewException("无法对损坏的对象执行操作。");}尝试{身体();}catch(Exception){this.IsCorrupted=true;如果(fixState()){this.IsCorrupted=false;}扔;}}}publicclassExampleUsage{privatereadonlyobjectExampleLock=newobject();privatereadonlyStateManagerstateManager=newStateManager();publicvoidExecuteLockedMethod(){lock(ExampleLock){stateManager.Execute(ExecuteMethod,EnsureValidState);}}privatevoidExecuteMethod(){//做一些事情,可能会抛出异常}publicboolEnsureValidState(){//确保状态有效的代码//如果有异常返回false,返回true;}}classStateManager{publicboolIsCorrupted{get;放;}publicvoidExecute(动作body,FuncfixState){if(this.IsCorrupted){//在这里使用一些异常派生类。thrownewException("无法对损坏的对象执行操作。");}尝试{身体();}catch(Exception){this.IsCorrupted=true;如果(fixState()){this.IsCorrupted=false;}扔;}}}publicclassExampleUsage{privatereadonlyobjectExampleLock=newobject();privatereadonlyStateManagerstateManager=newStateManager();publicvoidExecuteLockedMethod(){lock(ExampleLock){stateManager.执行(ExecuteMethod,EnsureValidState);}}privatevoidExecuteMethod(){//做一些事情,可能会抛出异常}publicboolEnsureValidState(){//确保状态有效的代码//如果有异常返回false,返回true;此外,据我所知,本文的要点是当并发存在时状态管理更难,但它仍然只是一个与锁定正交的对象状态正确性问题可能需要完全不同的方法来确保正确性。例如,不是使用锁定的代码区域来更改某些复杂状态,而是创建一个新状态,如果成功,只需在一个简单的引用分配中切换到新状态:);publicvoidExecuteLockedMethod(){varnewState=this.state.ExecuteMethod();this.state=newState;}}publicclassExampleUsageState{publicExampleUsageStateExecuteMethod(){//做某事,可能会抛出异常}}publicclassUsageExample{privateExampleUsageStatestate=newExampleUsageState();publicvoidExecuteLockedMethod(){varnewState=this.state.ExecuteMethod();this.state=newState;}}publicclassExampleUsageState{publicExampleUsageStateExecuteMethod(){//,dossomethingmaybethrowsanexception}}就个人而言,我一直倾向于认为手动锁定很难在需要时单独处理每个案例(所以没有太多需要通用状态管理解决方案)和低级工具才能真正谨慎地使用它。虽然它看起来很可靠,但我有三个担忧:1)每个锁定操作的Invoke()的性能成本可能很高。2)如果action(方法)需要参数怎么办?需要更复杂的解决方案。3)CorruptionStateDictionary是否会无限增长?我认为uncorrupt()方法应该删除对象而不是将数据设置为false。移动IsCorrupt测试和Monitor.EnterinTry将损坏设置处理移出finally并进入Catch块(这应该只在抛出异常时完成)不要在设置损坏标志之前释放主锁(将其保留在final块中)不要将异常限制为调用线程;通过将bool替换为自定义execption或将其添加到腐败字典并使用IsCorrupt返回它来重新创建它检查是否未损坏,只需删除项目锁定排序有一些问题(见下文)这应该涵盖所有基础publicstaticclassLocking{privatestaticreadonlyDictionaryCorruptionStateDictionary=newDictionary();私有静态只读对象CorruptionLock=newobject();publicstaticboolTryLockedAction(objectlockObject,Actionaction,outException){varexceptionlockTaken=false;异常=空;尝试{Monitor.Enter(lockObject,reflockTaken);if(IsCorrupt(lockObject)){exception=newLockingException("无法对损坏的对象执行锁定操作。");返回假;}action.Invoke();}catch(Exceptionex){varcorruptionLockTaken=false;异常=前;尝试{Monitor.Enter(CorruptionLock,refcorruptionLockTaken);if(CorruptionStateDictionary.ContainsKey(lockObject)){腐败ionStateDictionary[lockObject]=ex;}else{CorruptionStateDictionary.Add(lockObject,ex);}}finally{if(corruptionLockTaken){Monitor.Exit(CorruptionLock);}}}finally{if(lockTaken){Monitor.Exit(lockObject);}}返回异常==null;}publicstaticvoidUncorrupt(objectcorruptLockObject){varlockTaken=false;尝试{Monitor.Enter(CorruptionLock,reflockTaken);如果(IsCorrupt(corruptLockObject)){{CorruptionStateDictionary.Remove(corruptLockObject);}}}finally{if(lockTaken){Monitor.Exit(CorruptionLock);}}}publicstaticboolIsCorrupt(objectlockObject){Exceptionex=null;返回IsCorrupt(lockObject,outex);}publicstaticboolIsCorrupt(objectlockObject,outExceptionex){varlockTaken=false;前=空;尝试{Monitor.Enter(CorruptionLock,reflockTaken);如果(CorruptionStateDictionary.ContainsKey(lockObject)){ex=CorruptionStateDictionary[lockObject];}返回CorruptionStateDictionary.ContainsKey(锁定对象);}finally{if(lockTaken){Monitor.Exit(CorruptionLock);我建议的方法是为需要访问受保护资源的应用程序提供一个带有“inDangerState”字段的锁状态管理器对象。首先使用锁管理器对象获取锁;管理器将代表应用程序获取锁并检查inDangerState标志。如果设置,管理器将在展开堆栈时抛出异常并释放锁。否则,管理器会向应用程序返回一个IDisposable,这会释放对Dispose的锁定,但也可以操纵危险状态标志。在将锁定资源置于不良状态之前,应在IDisposable上调用一个方法,该方法将设置inDangerState并返回一个令牌,一旦锁定资源返回安全状态,该令牌可用于重新清除锁定资源。如果在重新清除inDangerState标志之前IDisposable被处置,资源将“卡住”在“危险”状态。可以将锁定资源恢复到安全状态的异常处理程序应该在返回或传播异常之前使用它来清除inDangerState标志。如果异常处理程序无法将锁定的资源恢复到安全状态,则应在设置inDangerState时传播异常。这种模式似乎比您所建议的更简单,但似乎比假设所有异常都会破坏锁定的资源,或者它们都不会破坏要好。以上是C#学习教程:加锁和管理加锁异常的解决方法有什么问题?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
