释放文件锁时收到通知
Getting notified when a file lock is released
[使用 C# 和 Windows 作为平台]
我有一台相机,可以将 JPG 文件写入我 PC 的本地文件夹。我想加载相机掉落的每个文件,所以我有一个 FileSystemWatcher,每当创建新图片时它都会通知我,但是相机在写入文件时锁定了文件,所以如果我尝试在收到创建通知后立即加载它,我得到一个异常提示 文件已锁定。
目前,我有一个 while 循环(带有 Thread.Sleep)每 0.2 秒重试一次加载图像,但感觉有点脏。
有没有更优雅的方法来等到锁被释放,这样我就可以加载文件并确保它不再被使用??
您将无法绕过试错法,即尝试打开文件,捕获 IOException,然后重试。但是,您可以像这样在单独的 class 中隐藏这种丑陋之处:
public class CustomWatcher
{
private readonly FileSystemWatcher watcher;
public event EventHandler<FileSystemEventArgs> CreatedAndReleased;
public CustomWatcher(string path)
{
watcher = new FileSystemWatcher(path, "*.jpg");
watcher.Created += OnFileCreated;
watcher.EnableRaisingEvents = true;
}
private void OnFileCreated(object sender, FileSystemEventArgs e)
{
// Running the loop on another thread. That means the event
// callback will be on the new thread. This can be omitted
// if it does not matter if you are blocking the current thread.
Task.Run(() =>
{
// Obviously some sort of timeout could be useful here.
// Test until you can open the file, then trigger the CreeatedAndReleased event.
while (!CanOpen(e.FullPath))
{
Thread.Sleep(200);
}
OnCreatedAndReleased(e);
});
}
private void OnCreatedAndReleased(FileSystemEventArgs e)
{
CreatedAndReleased?.Invoke(this, e);
}
private static bool CanOpen(string file)
{
FileStream stream = null;
try
{
stream = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.None);
}
catch (IOException)
{
return false;
}
finally
{
stream?.Close();
}
return true;
}
}
这个"watcher"可以这样使用:
var watcher = new CustomWatcher("path");
watcher.CreatedAndReleased += (o,e) =>
{
// Now, your watcher has managed to open and close the file,
// so the camera is done with it. Obviously, any other application
// is able to lock it before this code manages to open the file.
var stream = File.OpenRead(e.FullPath);
}
免责声明:CustomWatcher 可能需要 IDisposable 并适当地处理 FileSystemWatcher。该代码仅显示了如何实现所需功能的示例。
[使用 C# 和 Windows 作为平台]
我有一台相机,可以将 JPG 文件写入我 PC 的本地文件夹。我想加载相机掉落的每个文件,所以我有一个 FileSystemWatcher,每当创建新图片时它都会通知我,但是相机在写入文件时锁定了文件,所以如果我尝试在收到创建通知后立即加载它,我得到一个异常提示 文件已锁定。
目前,我有一个 while 循环(带有 Thread.Sleep)每 0.2 秒重试一次加载图像,但感觉有点脏。
有没有更优雅的方法来等到锁被释放,这样我就可以加载文件并确保它不再被使用??
您将无法绕过试错法,即尝试打开文件,捕获 IOException,然后重试。但是,您可以像这样在单独的 class 中隐藏这种丑陋之处:
public class CustomWatcher
{
private readonly FileSystemWatcher watcher;
public event EventHandler<FileSystemEventArgs> CreatedAndReleased;
public CustomWatcher(string path)
{
watcher = new FileSystemWatcher(path, "*.jpg");
watcher.Created += OnFileCreated;
watcher.EnableRaisingEvents = true;
}
private void OnFileCreated(object sender, FileSystemEventArgs e)
{
// Running the loop on another thread. That means the event
// callback will be on the new thread. This can be omitted
// if it does not matter if you are blocking the current thread.
Task.Run(() =>
{
// Obviously some sort of timeout could be useful here.
// Test until you can open the file, then trigger the CreeatedAndReleased event.
while (!CanOpen(e.FullPath))
{
Thread.Sleep(200);
}
OnCreatedAndReleased(e);
});
}
private void OnCreatedAndReleased(FileSystemEventArgs e)
{
CreatedAndReleased?.Invoke(this, e);
}
private static bool CanOpen(string file)
{
FileStream stream = null;
try
{
stream = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.None);
}
catch (IOException)
{
return false;
}
finally
{
stream?.Close();
}
return true;
}
}
这个"watcher"可以这样使用:
var watcher = new CustomWatcher("path");
watcher.CreatedAndReleased += (o,e) =>
{
// Now, your watcher has managed to open and close the file,
// so the camera is done with it. Obviously, any other application
// is able to lock it before this code manages to open the file.
var stream = File.OpenRead(e.FullPath);
}
免责声明:CustomWatcher 可能需要 IDisposable 并适当地处理 FileSystemWatcher。该代码仅显示了如何实现所需功能的示例。