正确的方法是使用写入锁(例如System.IO.FileAccess.Write和读取共享(例如System.IO.FileShare.Read))打开文件。如果其中一个当其他进程已经打开文件时,进程会尝试打开该文件,然后open命令会抛出一个异常,您需要捕捉并处理您认为合适的(例如,日志和重试)。通过使用写入锁文件打开,你保证开启和锁定是原子,因此两个进程之间的同步,而且没有竞争条件
因此,像这样:
try
{
using (FileStream fileStream = new FileStream(FileName, FileMode.Open, FileAccess.Write, FileShare.Read))
{
// Read from or write to file.
}
}
catch (IOException ex)
{
// The file is locked by the other process.
// Some options here:
// Log exception.
// Ignore exception and carry on.
// Implement a retry mechanism to try opening the file again.
}
如果在程序打开时不希望其他进程能够访问文件,则可以使用FileShare.None。我更喜欢FileShare。阅读是因为它允许我监视文件中发生了什么(例如,在记事本中打开它)。
为配合删除该文件是一个类似的原则:第一重命名/移动文件和赶上,如果其他进程已重新命名/移动它发生IOException异常,然后打开改名/移动文件。您重命名/移动该文件以指示文件已被处理,并且应该被其他进程忽略。例如,用一个悬而未决的文件扩展名重新命名它,或者将它移动到一个待定目录。
try
{
// This will throw an exception if the other process has already moved the file -
// either FileName no longer exists, or it is locked.
File.Move(FileName, PendingFileName);
// If we get this far we know we have exclusive access to the pending file.
using (FileStream fileStream = new FileStream(PendingFileName, FileMode.Open, FileAccess.Write, FileShare.Read))
{
// Read from or write to file.
}
File.Delete(PendingFileName);
}
catch (IOException ex)
{
// The file is locked by the other process.
// Some options here:
// Log exception.
// Ignore exception and carry on.
// Implement a retry mechanism to try moving the file again.
}
如同打开文件,File.Move是原子和锁保护,因此可以保证,如果你有试图移动文件多个并发线程/进程中,只有一个会成功,别人就会抛出一个例外。在这里看到一个类似的问题:Atomicity of File.Move。
这很直截了当,但是因为我也想删除文件(在代码中使用using语句之后会出现File.Delete命令),您如何确保其他实例不会尝试访问文件之间的结尾使用语句(文件锁)和删除?你能将你的代码扩展到完整流程吗? – ithinkyes