简体   繁体   English

如何在C#中使进程(而不是线程)同步文件系统访问

[英]How to have processes (not threads) in C# synchronize file system access

Earlier today I was debugging something that went a bit like this: 今天早些时候我正在调试有点像这样的东西:

class Foo {

    void AccessCriticalSection() {
        try {
            if (IO.File.Exists("\\path\to\lock.txt")
                throw new Exception();
            System.IO.File.Create("\\path\to\lock.txt");
            criticalSection();          
        } catch (Exception ex) {
            // ignored
        } 
    }

    void CriticalSection() {
        // banana banana banana
        System.IO.File.Delete("\\path\to\lock.txt");
    }

}

Let's not even get into how terrible this is… but it's essentially trying to use a file called lock.txt as its mutex. 让我们甚至不知道这是多么可怕......但它本质上是试图使用一个名为lock.txt的文件作为它的互斥体。 The operation isn't atomic, other processes are just not getting through the critical section if another process is using it (they're intended to be able to continue after the lock is released if you can believe it), etc. etc. Obviously it needs to be fixed. 该操作不是原子操作,如果另一个进程正在使用它,其他进程只是没有通过关键部分(如果您可以相信它们,它们的目的是能够在锁定释放后继续)等等。显然它需要修复。

How do I properly obtain a lock to synchronize access to the filesystem across multiple processes? 如何正确获取锁以跨多个进程同步对文件系统的访问? The processes are multiple instances of the same process, so they can share some protocol rather than specifically locking the directory (ie, they can easily use what is the equivalent to all instances of some class locking on something like private final static Object lock = new Object(); to synchronize access to static methods) 这些进程是同一进程的多个实例,因此它们可以共享一些协议而不是专门锁定目录(即,它们可以轻松地使用等同于某些类锁定的所有实例的东西,如private final static Object lock = new Object();同步访问静态方法)

You should use a Mutex . 你应该使用Mutex

A synchronization primitive that can also be used for interprocess synchronization . 同步原语,也可用于进程间同步

Mutexes are either local to a process or named . 互斥锁是进程的本地命名 To support interprocess synchronization you'll need to use a named mutex . 要支持进程间同步,您需要使用命名的互斥锁

Named system mutexes are visible throughout the operating system, and can be used to synchronize the activities of processes. 命名系统互斥体在整个操作系统中都是可见的,可用于同步进程的活动。


Here's a sample program that demonstrate interprocess synchronization using a shared mutex. 这是一个示例程序,它使用共享互斥锁演示进程间同步。

class Program
{
    static void Main(string[] args)
    {
        const string SHARED_MUTEX_NAME = "something";
        int pid = Process.GetCurrentProcess().Id;

        using (Mutex mtx = new Mutex(false, SHARED_MUTEX_NAME))
        {
            while (true)
            {
                Console.WriteLine("Press any key to let process {0} acquire the shared mutex.", pid);
                Console.ReadKey();

                while (!mtx.WaitOne(1000))
                {
                    Console.WriteLine("Process {0} is waiting for the shared mutex...", pid);
                }

                Console.WriteLine("Process {0} has acquired the shared mutex. Press any key to release it.", pid);
                Console.ReadKey();

                mtx.ReleaseMutex();
                Console.WriteLine("Process {0} released the shared mutex.", pid);
            }
        }            
    }
}

Sample program output: 示例程序输出:

mutex_test

The purple lines show points where control of the shared mutex is transferred between the two processes. 紫色线条表示在两个进程之间传输共享互斥锁控制的点。


To synchronize access to individual files you should use a mutex name that is based on a normalized path of the protected file. 要同步对单个文件的访问,应使用基于受保护文件的规范化路径的互斥锁名称。

Here's how you can create a normalized path : 以下是创建规范化路径的方法

public static string NormalizePath(string path)
{
    return Path.GetFullPath(new Uri(path).LocalPath)
               .TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)
               .ToUpperInvariant();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM