如何在委托

时间:2016-06-22 06:31:02

标签: c# multithreading design-patterns delegates

我正在尝试创建一个接受委托的通用方法。该方法的唯一目的是确保传递给它的任何唯一代码块,一次只能由一个线程访问。我指出这个单词是唯一的,因为唯一的代码块可以并行运行,重复的代码块必须同步运行。是否有一个干净的模式来实现这一目标?

2 个答案:

答案 0 :(得分:2)

您可以这样做:

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();
            }
        }
    }
}

答案 1 :(得分:0)

最终,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();
                }
            }
        }
    }
}