4

我正在使用 C# 编写一个 ASP.NET Web 应用程序,它可以从 IIS 服务器(使用System.IO.FileStream)读取和写入文本文件,我想知道如何在此操作上实现全局锁定?

4

5 回答 5

3

对于全局锁,您需要互斥锁

    // The key can be part of the file name - 
    //   be careful not all characters are valid
    var mut = new Mutex(true, key);

    try
    {   
        // Wait until it is safe to enter.
        mut.WaitOne();

        // here you manipulate your file
    }
    finally
    {
        // Release the Mutex.
        mut.ReleaseMutex();
    }   
于 2013-03-03T00:44:35.353 回答
1

最简单的解决方案是在 Cache 或 Application 对象中创建一个新对象,最好是在 global.asax 文件中的 Application_Startup 中。如:

Cache["myLocker"] = new object();

然后您可以使用标准的“锁定”语法。

lock(Cache["myLocker"]) 
{
  // do file access here...
}
于 2013-03-03T00:58:14.937 回答
1

根据@Aristos 的建议和这篇文章,我想出了这门课:

using System.Threading;
using System.Security.AccessControl;
using System.Security.Principal;

using System.Runtime.InteropServices;   //GuidAttribute
using System.Reflection;                //Assembly

namespace ITXClimateSaverWebApp
{
    public class GlobalNamedLock
    {
        private Mutex mtx;

        public GlobalNamedLock(string strLockName)
        {
        //Name must be provided!
            if(string.IsNullOrWhiteSpace(strLockName))
            {
                //Use default name
                strLockName = ((GuidAttribute)Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(GuidAttribute), false).GetValue(0)).Value.ToString();
            }

            //Create security permissions for everyone
            //It is needed in case the mutex is used by a process with
            //different set of privileges than the one that created it
            //Setting it will avoid access_denied errors.
            MutexSecurity mSec = new MutexSecurity();
            mSec.AddAccessRule(new MutexAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null),
                MutexRights.FullControl, AccessControlType.Allow));

            //Create the global mutex
            bool bCreatedNew;
            mtx = new Mutex(false, @"Global\" + strLockName, out bCreatedNew, mSec);
        }

        public bool enterCRITICAL_SECTION()
        {
            //Enter critical section
            //INFO: May throw an exception!
            //RETURN:
            //      = 'true' if successfully entered
            //      = 'false' if failed (DO NOT continue!)

            //Wait
            return mtx.WaitOne();
        }

        public void leaveCRITICAL_SECTION()
        {
            //Leave critical section
            //INFO: May throw an exception!

            //Release it
            mtx.ReleaseMutex();
        }
    }
}

然后将其称为全局锁的方式:

try
{
    GlobalNamedLock gl = new GlobalNamedLock("MyLockName");

    try
    {
        if (gl.enterCRITICAL_SECTION())
        {
            //Use the global resource now
        }
    }
    finally
    {
        gl.leaveCRITICAL_SECTION();
    }
}
catch (Exception ex)
{
    //Failed -- log it
}

所以这似乎可以完成这项工作。你怎么看?

于 2013-03-03T01:56:17.140 回答
0

为什么不只使用全局同步根对象?

internal static class Lock
{
    public static object SyncRoot = new object{};
}

用法:

lock (Lock.SyncRoot)
{
}
于 2013-03-03T02:07:12.963 回答
0

命名互斥体是系统对象。与 lock 关键字不同,它们甚至可以跨进程边界工作。锁定仅在同步同一进程中的线程的上下文中有用。

于 2020-11-21T14:40:47.143 回答