him*_*msy 10 c# file-io multithreading
我们目前有一个应用程序监视新文件的文件夹.为了使其具有容错能力并能够一次处理更多文件,我们希望能够在不同的计算机上运行此应用程序的多个实例.我们使用File.Move"锁定"文件并确保一次只有一个线程可以处理文件.
为了测试只有一个应用程序和/或线程可以File.Move对文件执行,我创建了一个简单的应用程序(基于原始应用程序的代码),每个应用程序创建10个线程并监视文件夹,当每个线程检测到一个新文件时,它执行File.Move它并更改文件的扩展名,以尝试阻止其他线程执行相同操作.
我在运行此应用程序的多个副本时遇到了一个问题(并且它自己运行),其中2个线程(在同一个应用程序中或不同的应用程序中)都成功执行File.Move,没有异常抛出,但最后执行它的线程(我更改了文件的扩展名以包含DateTime.Now.ToFileTime()),成功重命名了该文件.我已经查看了File.Move它在执行操作之前检查文件是否存在,然后调用Win32Native.MoveFile以执行移动.
正如我所料,所有其他线程/应用程序都会抛出异常.
这是一个问题的原因是:
File.Move一个文件.以下是执行以下操作的代码File.Move:
public bool TryLock(string originalFile, out string changedFileName)
{
FileInfo fileInfo = new FileInfo(originalFile);
changedFileName = Path.ChangeExtension(originalFile, ".original." + DateTime.Now.ToFileTime());
try
{
File.Move(originalFile, changedFileName);
}
catch (IOException ex)
{
Console.WriteLine("{3} - Thread {1}-{2} File {0} is already in use", fileInfo.Name, Thread.CurrentThread.ManagedThreadId, id, DateTime.Now.ToLongTimeString());
return false;
}
catch (Exception ex)
{
Console.WriteLine("{3} - Thread {1}-{2} File {0} error {4}", fileInfo.Name, Thread.CurrentThread.ManagedThreadId, id, DateTime.Now.ToLongTimeString(), ex);
return false;
}
return true;
}
Run Code Online (Sandbox Code Playgroud)
注 - id只是我分配给每个线程进行日志记录的序号.
我在带有NTFS的SSD上运行Windows 7 Enterprise SP1.
根据@marceln和@YuvalItzchakov的回答/评论,我尝试了以下方法,这似乎给出了更可靠的结果:
using (var readFileStream = File.Open(originalFile, FileMode.Open, FileAccess.Read, FileShare.Delete))
{
readFileStream.Lock(0, readFileStream.Length - 1);
File.Move(originalFile, changedFileName);
readFileStream.Unlock(0, readFileStream.Length - 1);
}
Run Code Online (Sandbox Code Playgroud)
我想使用 Windows 自己的文件复制,因为它应该比复制流更有效,并且在生产中我们会将文件从一个网络共享移动到另一个网络共享。
| 归档时间: |
|
| 查看次数: |
1128 次 |
| 最近记录: |