2008-08-23 20 views
7

En C#, je peux utiliser l'objet FileSystemWatcher pour surveiller un fichier spécifique et déclencher un événement lorsqu'il est créé, modifié, etc.Est-il possible de déclencher un événement lorsqu'un fichier devient accessible?

Le problème que j'ai avec cette classe est qu'elle soulève l'événement au moment où le fichier devient créé, même si le processus qui a créé le fichier est encore en cours d'écriture. J'ai trouvé cela très problématique, surtout si j'essaie de lire quelque chose comme un document XML où le fichier doit avoir une structure qui n'existera pas jusqu'à ce qu'il soit écrit.

Est-ce que .NET (de préférence 2.0) a un moyen de déclencher un événement après que le fichier soit accessible, ou dois-je constamment essayer de lire le fichier jusqu'à ce qu'il ne lève pas une exception?

Répondre

0

Je ne sais pas s'il existe un moyen pour un événement d'être levé par la classe standard, mais j'éprouve facilement des problèmes similaires sur un travail récent que je faisais. En bref, j'essayais d'écrire dans un fichier qui était verrouillé à ce moment-là. J'ai fini par encapsuler la méthode d'écriture afin qu'elle essaie automatiquement l'écriture dans quelques ms après.

Penser à haute voix, pouvez-vous sonder le fichier pour un état de ReadOnly? Peut-être vaut alors avoir un wrapper pour le fichier IO qui peut empiler des délégués pour des opérations de fichiers en attente ou quelque chose .. Pensées?

0

Utilisation CreateFile dans une boucle avec open_ EXISTANT drapeau et ACCESS fichier_ ALL_ (ou vous pourriez avoir besoin que d'un sous-ensemble, voir http://msdn.microsoft.com/en-us/library/aa364399(VS.85).aspx

Examiner la poignée retournée contre -1 (INVALID_ HANDLE_ VALUE) pour l'échec. Il est encore sondage , mais cela permettra d'économiser le coût d'un jet d'exception

EDIT:. cet éditeur/balisage ne peut pas gérer underscores bah

5

Vous pouvez utiliser un veilleur de système de fichiers pour vérifier si le fichier a été changé!. Il ne devient "changé" après que le programme a eu le fichier ferme le fi le. Je sais que vous avez demandé C#, mais mon VB.Net est beaucoup mieux. J'espère que vous ou quelqu'un d'autre peut traduire.

Il essaie d'ouvrir le fichier, s'il n'est pas disponible, il ajoute un observateur et attend que le fichier soit modifié. Une fois le fichier modifié, il essaie d'ouvrir à nouveau. Il déclenche une exception s'il attend plus de 120 secondes, car vous risquez de vous retrouver dans une situation où le fichier n'est jamais publié. En outre, j'ai décidé d'ajouter un délai d'attente pour le changement de fichier de 5 secondes, dans le cas de la petite possibilité que le fichier a été fermé avant la création du fichier observateur réel.

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 
0

Kibbe réponse semble juste mais n'a pas fonctionné pour moi. Il semble que le FileSystemWatcher a un bug. J'ai donc écrit mon propre 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(); 
    } 
} 
+0

Veuillez signaler ce problème à Microsoft à l'adresse http://connect.microsoft.com/visualstudio. –

+0

[John Aldrige] (http://www.devnewsgroups.net/group/microsoft.public.dotnet.framework/topic56372.aspx) l'a déjà fait [it] (https://connect.microsoft.com/VisualStudio/feedback/ ViewFeedback.aspx? FeedbackID = 240502) –

+0

Le lien @JaderDias Connect est rompu –