C# 如何在委托上强制执行互斥
我正在尝试创建一个接受委托的泛型方法。该方法的唯一目的是确保传递给它的任何唯一代码块一次只能由一个线程访问。我指出了唯一这个词,因为唯一的代码块可以并排运行,重复的代码块必须同步运行。是否有一个干净的模式来实现这一点?您可以这样做:C# 如何在委托上强制执行互斥,c#,multithreading,design-patterns,delegates,C#,Multithreading,Design Patterns,Delegates,我正在尝试创建一个接受委托的泛型方法。该方法的唯一目的是确保传递给它的任何唯一代码块一次只能由一个线程访问。我指出了唯一这个词,因为唯一的代码块可以并排运行,重复的代码块必须同步运行。是否有一个干净的模式来实现这一点?您可以这样做: namespace RunSafe { // Declare a delegate type public delegate void RunSafeDelegate(); public class SafeRunner {
namespace RunSafe
{
// Declare a delegate type
public delegate void RunSafeDelegate();
public class SafeRunner
{
private object _lock = new Object();
public void Runner( RunSafeDelegate runsafe )
{
lock( this._lock )
{
runsafe();
}
}
}
}
最终,Dex Star的代码示例引导我走上了我所寻找的道路 如果有任何问题,请让我知道。我相信这是一个坚实的解决方案。注意,我故意使用一个命名互斥,因为访问资源可能涉及多个进程
// test code
RunSafeDelegate rsd1 = () => { /* some code i need synchronous */ };
RunSafeDelegate rsd2 = () => { /* other code i need synchronous */ };
var util = new UtilityClass();
util.RunSafe(rsd1, "myMutexName1");
util.RunSafe(rsd2, "myMutexName2");
// implementation
public class UtilityClass
{
public delegate void RunSafeDelegate();
public void RunSafe(RunSafeDelegate runSafe, string mutexName)
{
const int WAIT_ONE_TIMEOUT = 30000;
var sid = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
var mar = new MutexAccessRule(sid, MutexRights.FullControl, AccessControlType.Allow);
var ms = new MutexSecurity();
ms.AddAccessRule(mar);
bool mutexCreated;
using(var mutex = new Mutex(false, mutexName, out mutexCreated, ms))
{
var signalReceived = false;
try
{
try
{
signalReceived = mutex.WaitOne(WAIT_ONE_TIMEOUT, false);
if(!signalReceived)
{
throw new TimeoutException("Exclusive access timeout for mutex: " + mutexName);
}
}
catch(AbandonedMutexException)
{
signalReceived = true;
}
runSafe();
}
finally
{
if(signalReceived)
{
mutex.ReleaseMutex();
}
}
}
}
}
使用互斥、锁定或二年级学生?你到底试了什么?我都试过了。我真的在寻找主要基于需求的正确模式。@Mekap:你是说信号量?@JimMischel是的。确切地说:$如何识别“唯一代码”?给我们看一些例子。谢谢Dex。只有当代码块相同时,才有办法强制执行锁吗?我基本上需要它来扩展,这样,如果出现不同的代码块,它应该将其作为一个单独的锁来处理。@user1701153这不是一个好方法。代码是不可变的。它不必受到保护。锁保护数据,而不是代码。@usr代码最终会对我需要保护的东西起作用。例如,我可能要传递的一个代码块是获得一个免费的tcp端口。我想同步它以避免冲突。等等。只有当每个人都使用相同的
SafeRunner
实例时,这才有效,这样您就不能一次运行多个实例了。@JimMischel同意。对更好的设计有什么建议吗?我很高兴你得到了你需要的。如果您使用的是互斥体,那么它们是IDisposable的,因此您需要使用(var mutex=new mutex(false,mutexName)){}
。。。另外,由于您的类不再具有实例成员,您可以使其及其方法静态,并避免必须实例化它。@DexStar感谢Dex。非常感谢你的建议。我已经根据您的反馈和在另一篇帖子中找到的一些重要信息更新了我的实现: