我需要将日志数据写入来自不同进程的单个文件中。
我正在使用Windows Mutex,它需要Common Language Runtime支持。
Mutex^ m = gcnew Mutex( false,"MyMutex" );
m->WaitOne();
//... File Open and Write ..
m->ReleaseMutex()
我是否真的需要从C ++更改为C ++ / CLI进行同步?
如果不使用原子就可以了。但我需要知道,与本地互斥锁相比,使用此互斥锁是否会降低性能。
答案 0 :(得分:6)
为获取Mutex类而向您的C ++应用程序添加CLR支持是过度的。您可以使用多个选项在两个应用程序之间同步文件访问。
如果您需要从多个进程编写文件,使用互斥锁是一种很好的方法。使用Win32 API中的mutex functions。 (无论如何,.Net Mutex类只是这些函数的包装。)
HANDLE mutex = CreateMutex(NULL, false, "MyMutex");
DWORD waitResult = WaitForSingleObject(mutex, INFINITE);
if (waitResult == WAIT_OBJECT_0)
{
// TODO: Write the file
WriteFile(...);
ReleaseMutex(mutex);
}
正如另一个答案所指出的那样,您需要使用共享打开文件,这样您的两个应用程序都可以立即打开它。但是,这本身可能还不够:如果两个应用程序都试图写入文件的同一区域,那么您仍然需要确保一次只能写入一个应用程序。想象一下,如果两个应用程序都查看文件的大小,那么它们都会尝试同时写入该字节偏移量:尽管两者都试图只追加到文件的末尾,但它们最终会互相破坏。
如果您纯粹写到文件的末尾,并且从未尝试读取任何内容或在文件的最末端以外的任何地方写入,那么您可以使用一种特殊模式你不使用互斥锁。如果您打开文件时dwDesiredAccess
设置为FILE_APPEND_DATA | SYNCHRONIZE
而没有其他(不包括FILE_WRITE_DATA
),那么操作系统将负责制作确保最后写入文件的所有数据,以及写入数据的两个应用程序不会相互覆盖。 MSDN上记录了此行为:
如果仅设置了FILE_APPEND_DATA和SYNCHRONIZE标志,则调用者只能写入文件的末尾,并且忽略有关写入文件的任何偏移信息。但是,对于此类写入操作,文件将根据需要自动扩展。
您可以采用的另一种方法是使用LockFile
方法。使用LockFile
(或LockFileEx
),您可以让两个应用程序打开文件,并让每个应用程序锁定要写入的文件部分。这为您提供了比互斥锁更多的粒度,允许同时发生非重叠写入。 (在整个文件上使用LockFile
将为您提供与互斥锁相同的基本效果,还有一个额外的好处,即它会阻止其他应用程序在您执行此操作时写入文件。)'如何在Raymond Chen's blog上使用LockFile
的一个很好的例子。
答案 1 :(得分:1)
实际上你根本不需要使用单独的互斥锁,你可以只使用文件本身。当使用CreateFile API调用打开文件时(请参阅https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396),该调用将使用一个名为dwShareMode的参数,该参数指定其他进程允许的并发访问。值为0将阻止其他进程完全打开文件。
几乎所有用于打开文件映射到CreateFile的API都是如此,因此当您打开文件进行写入时,clr可能正在为您做正确的事。
在C运行时中还有_fsopen,它允许您使用共享标志打开文件。
我建议您测试从C#打开文件时的默认共享模式。如果默认情况下不会阻止同时打开写入,请使用C中的_fsopen(或者可能有适当的C#函数)。