C# 当文件变得可访问时是否可以引发事件?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24315/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is It Possible To Raise An Event When A File Becomes Accessible?
提问by Dan Herbert
In C# I can use the FileSystemWatcher object to watch for a specific file and raise an event when it is created, modified, etc.
在 C# 中,我可以使用 FileSystemWatcher 对象来监视特定文件并在创建、修改等时引发事件。
The problem I have with this class is that it raises the event the moment the file becomes created, even if the process which created the file is still in the process of writing. I have found this to be very problematic, especially if I'm trying to read something like an XML document where the file must have some structure to it which won't exist until it is completed being written.
我对这个类的问题是它在文件创建的那一刻引发事件,即使创建文件的进程仍在写入过程中。我发现这是非常有问题的,尤其是当我尝试读取 XML 文档之类的内容时,该文件必须具有某种结构,并且在完成写入之前不会存在。
Does .NET (preferably 2.0) have any way to raise an event after the file becomes accessible, or do I have to constantly try reading the file until it doesn't throw an exception to know it is available?
.NET(最好是 2.0)有没有办法在文件变得可访问后引发事件,或者我是否必须不断尝试读取文件直到它不抛出异常才能知道它可用?
回答by Rob Cooper
Not sure if there is a way of an event actually being raised by the standard class, but I eas experiencing similar problems on some recent work I was doing.
不确定标准类是否有实际引发事件的方式,但我在最近的一些工作中遇到了类似的问题。
In short, I was trying to write to a file that was locked at the time. I ended up wrapping the write method up so it would automatically try the write again in a few ms after..
简而言之,我试图写入当时被锁定的文件。我最终包装了 write 方法,因此它会在几毫秒后自动再次尝试写入..
Thinking out loud, Can you probe the file for a ReadOnly status? May be worth then having a wrapper for file IO which can stack up delegates for pending file operations or something.. Thoughts?
大声思考,你能探测文件的只读状态吗?可能值得拥有一个文件 IO 的包装器,它可以为挂起的文件操作或其他东西堆叠委托.. 想法?
回答by Nick
Use CreateFilein a loop with OPEN_ EXISTING flag and FILE_ ALL_ ACCESS (or you might need only a subset, see http://msdn.microsoft.com/en-us/library/aa364399(VS.85).aspx
在带有 OPEN_ EXISTING 标志和 FILE_ ALL_ ACCESS 的循环中使用CreateFile(或者您可能只需要一个子集,请参阅http://msdn.microsoft.com/en-us/library/aa364399(VS.85).aspx
Examine the handle returned against -1 (INVALID_ HANDLE_ VALUE) for failure. It's still polling, but this will save the cost of an exception throw.
检查针对 -1 (INVALID_HANDLE_VALUE) 返回的句柄是否失败。它仍在轮询,但这将节省抛出异常的成本。
EDIT: this editor/markup can't handle underscores! bah!
编辑:这个编辑器/标记不能处理下划线!呸!
回答by Kibbee
You can use a file system watcher to check when the file has been changed. It only becomes "changed" after whichever program had the file previously closes the file. I know you asked for C#, but my VB.Net is much better. Hope you or someone else can translate.
您可以使用文件系统观察器来检查文件何时被更改。只有在任何程序之前关闭文件后,它才会“更改”。我知道你要求 C#,但我的 VB.Net 好多了。希望您或其他人可以翻译。
It tries to open the file, if it isn't available, it adds a watcher, and waits for the file to be changed. After the file is changed, it tries to open again. It throws an exception if it waits more than 120 seconds, because you may get caught in a situation where the file is never released. Also, I decided to add a timeout of waiting for the file change of 5 seconds, in case of the small possibility that the file was closed prior to the actual file watcher being created.
它尝试打开文件,如果它不可用,它会添加一个观察者,并等待文件被更改。文件更改后,它会尝试再次打开。如果等待超过 120 秒,它会抛出异常,因为您可能会陷入文件从未被释放的情况。此外,我决定添加等待文件更改 5 秒的超时时间,以防在创建实际文件观察程序之前文件已关闭的可能性很小。
Public Sub WriteToFile(ByVal FilePath As String, ByVal FileName As String, ByVal Data() As Byte)
Dim FileOpen As Boolean
Dim File As System.IO.FileStream = Nothing
Dim StartTime As DateTime
Dim MaxWaitSeconds As Integer = 120
StartTime = DateTime.Now
FileOpen = False
Do
Try
File = New System.IO.FileStream(FilePath & FileName, IO.FileMode.Append)
FileOpen = True
Catch ex As Exception
If DateTime.Now.Subtract(StartTime).TotalSeconds > MaxWaitSeconds Then
Throw New Exception("Waited more than " & MaxWaitSeconds & " To Open File.")
Else
Dim FileWatch As System.IO.FileSystemWatcher
FileWatch = New System.IO.FileSystemWatcher(FilePath, FileName)
FileWatch.WaitForChanged(IO.WatcherChangeTypes.Changed,5000)
End If
FileOpen = False
End Try
Loop While Not FileOpen
If FileOpen Then
File.Write(Data, 0, Data.Length)
File.Close()
End If
End Sub
回答by Jader Dias
Kibbe answer seems right but didn't worked for me. It seems that the FileSystemWatcher has a bug. So I wrote my own WaitForChanged:
Kibbe 的答案似乎是正确的,但对我不起作用。FileSystemWatcher 似乎有一个错误。所以我写了我自己的WaitForChanged:
using (var watcher = new FileSystemWatcher(MatlabPath, fileName))
{
var wait = new EventWaitHandle(false, EventResetMode.AutoReset);
watcher.EnableRaisingEvents = true;
watcher.Changed += delegate(object sender, FileSystemEventArgs e)
{
wait.Set();
};
if (!wait.WaitOne(MillissecondsTimeout))
{
throw new TimeoutException();
}
}