我有一个进程 A 读取由其他进程 B 生成的一些数据。数据通过文件系统“交换”。为确保文件存在,进程 A 当前检查文件是否存在,如下所示:
while (!File.Exists(FileLocation))
{
Thread.Sleep(100);
}
这似乎只有 99% 的时间有效。另外 1% 的时间,进程 A 确定文件存在,但进程 B 尚未写入所有内容(即丢失了一些数据)。
是否有另一种更简单的方法可以使上述情况更加防弹?谢谢。
是否有另一种更简单的方法可以使上述情况更加防弹?
您可以使用 aMutex
进行可靠的进程间同步。另一种可能性是使用FileSystemWatcher
.
确定文件存在后,您可以尝试以独占方式打开文件,如果另一个进程仍然打开该文件,则会失败:
try
{
File.Open("foo",FileMode.Open,FileAccess.Read,FileShare.None);
}
catch(IOException ex)
{
// go back to
}
鉴于您说您可以更改两个进程的代码,您可以使用 EventWaitHandle 在进程之间进行通信。
在创建文件的程序中,在 Main() 方法中,您可以创建一个 EventWaitHandle 并保留它直到程序结束。您需要在程序中传递 EventWaitHandle 对象,以便它可用于创建文件的代码位(或提供一些方法,文件创建代码可以调用以设置事件)。
using (EventWaitHandle readySignaller = new EventWaitHandle(false, EventResetMode.ManualReset, "MySignalName"))
{
// Rest of program goes here...
// When your program creates the file, do this:
readySignaller.Set();
}
然后在等待文件的程序中有一些这样的代码:
// Returns true if the wait was successful.
// Once this has returned true, it will return false until the file is created again.
public static bool WaitForFileToBeCreated(int timeoutMilliseconds) // Pass Timeout.Infinite to wait infinitely.
{
using (EventWaitHandle readySignaller = new EventWaitHandle(false, EventResetMode.ManualReset, "MySignalName"))
{
bool result = readySignaller.WaitOne(timeoutMilliseconds);
if (result)
{
readySignaller.Reset();
}
return result;
}
}
注意:如果我们成功等待,请注意我正在重置信号,它将保持重置,直到其他进程再次设置它。如果需要,您可以以不同的方式处理逻辑;这只是一个例子。
本质上,我们(逻辑上)在这里所做的是在两个进程之间共享一个布尔值。您必须小心设置和重置该共享布尔值的顺序。
侦听文件系统更改通知并在目录或目录中的文件更改时引发事件。