c# - 如何让 C# 中的进程(而不是线程)同步文件系统访问

标签 c# windows multithreading

今天早些时候,我正在调试一个有点像这样的东西:

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

}

我们先不说这有多可怕……但它本质上是在尝试使用名为 lock.txt 的文件作为其互斥量。该操作不是原子的,如果另一个进程正在使用它,则其他进程只是没有通过临界区(如果您相信的话,它们旨在能够在释放锁后继续),等等。显然它需要修复。

如何正确获取锁以同步跨多个进程对文件系统的访问?这些进程是同一进程的多个实例,因此它们可以共享一些协议(protocol)而不是专门锁定目录(即,它们可以轻松地使用等同于某个类的所有实例锁定在诸如 private final static Object 之类的东西上lock = new Object(); 同步访问静态方法)

最佳答案

你应该使用 Mutex .

A synchronization primitive that can also be used for interprocess synchronization.

互斥体要么是进程的本地,要么是命名的。要支持进程间同步,您需要使用命名互斥体

Named system mutexes are visible throughout the operating system, and can be used to synchronize the activities of processes.


这是一个示例程序,它演示了使用共享互斥体的进程间同步。

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

示例程序输出:

mutex_test

紫色线表示共享互斥锁的控制在两个进程之间转移的点。


要同步对单个文件的访问,您应该使用基于 protected 文件的规范化路径的互斥锁名称。

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

关于c# - 如何让 C# 中的进程(而不是线程)同步文件系统访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30205648/

相关文章:

c# rdlc 无法为数据集 "ProjectDS_ObservationImages"创建 DataReader

c# - 从 Azure Blob 存储返回 PDF 时出现“错误,无法加载 PDF 文档”

java - 从 C# 关闭 java 进程(在 Windows 上)

windows - Qt - WINDOWS - 蓝牙低功耗工作?

python - Flask 线程共享值

java - 处理线程最大执行时间的最佳方法(在 Java 中)

Android 广播接收器 : perform network call and play sound

c# - 使用泛型获取属性信息

c# - SQL CROSS JOIN问题

windows - 为什么这个 FOR 命令不删除除我想保留的文件以外的所有文件?