我可以告诉其他进程是否正在创build文件?

我正在编写一个Windows服务来处理由我无法控制的另一个进程创build的文件。 这些文件可能会非常大(数百兆字节)。

我需要处理,然后在创build完成后删除这些文件。

所有的文件将被写入到一个特定的目录(就我所知,只是一个直接的文件副本),所以我可以定期遍历该目录中的文件,处理它们,然后删除它们。

我担心的是如果我的服务在编写大文件的时候查询目录会发生什么? 该文件将显示为我的服务? 它会被locking,所以我不能读取访问? 我是否需要做任何特殊的事情来检查文件是否已经完成复制,或者我可以查询File.Exists()或尝试使用FileAccess.Read打开它。 Windows如何标记正在复制过程中的文件?

如果这是简单的win32,你会尝试用CreateFile()和共享模式来打开文件,这种模式拒绝对其他人的写入访问。 如果其他程序仍然在写入文件,那么这将会失败,因为当文件已经以写入权限打开时,您不能拒绝写入访问。 如果成功,则知道其他进程已经完成。

例如,在.net中,您可以使用接收FileShare参数的构造函数之一来创建FileStream 。 这将最终映射到底层的CreateFile() API。

AFAIK在文件中没有特殊的标记来表明它正在被复制,除了它将有一个写锁。 这种情况下的标准做法是尝试使用写入锁(例如FileShare.Read)自己打开文件,并捕获由于文件已被锁定而发生的任何IOException。 在这种情况下,在重新打开文件之前暂停一下(Thread.Sleep)。 您可能需要限制重试的次数(以防止现有文件锁定从不释放时发生无限循环)。

你说你想处理文件,然后删除它们? 为了避免与其他进程/线程在处理/删除时写入同一文件的竞争,您应该将您的处理/删除视为一个原子操作,例如:

 string sourcePath = @"C:\temp1\temp.txt"; string targetPath = @"C:\temp2\temp.txt"; int attempt = 0; const int maxAttempts = 3; bool moved = false; do { try { File.Move(sourcePath, targetPath); moved = true; } catch (IOException) { if (attempt < maxAttempts) { System.Threading.Thread.Sleep(1000); attempt++; } } } while (!moved && attempt < maxAttempts); if (moved) { ProcessFile(targetPath); File.Delete(targetPath); } else { throw new InvalidOperationException("Unable to process '" + sourcePath + "'."); } 

编辑:我看你说这些文件可能是非常大的,所以你不应该使用File.ReadAllText。 您可以尝试将文件移动到另一个目录 – 这将引发异常,该文件仍然被其他进程锁定。 只有成功移动文件时才能处理文件。 这也有从输入目录中删除文件的好处。

用临时文件名写入文件,然后重命名文件。

重命名是一个惯常的过程,所以你的服务处理文件应该没问题。 只要确保该服务跳过临时文件名。