21. august 2012 - 18:12Der er
10 kommentarer og 1 løsning
Program til overvågning af mappe crasher efter noget tid
Hej
Jeg prøver at lave et program der hele tiden skal overvåge en mappe. Når den finder en ny fil i mappen skal den så udføre en konvertering af denne fil. Jeg har skrevet nedenstående kode som virker fint til at starte med. Men efter at den måske har kørt i en time så går programmet ned uden fejl. Er der en bedre måde at kode det på? Jeg vil desuden meget gerne have mulighed for at køre funktionen MakeFile() 2 gange parallelt på hver sin kerne (til overvågning af 2 forskellige mapper). Hvordan kan det gøres?
Jeg koder i Visual Basic Express 2010 og her er min kode:
Option Explicit On Imports System Imports System.IO Imports System.Threading
Public Class Form1 Public lineRead, Path1, AddText, PathConverter, WaitTime As String Public ConvertedCounter As Integer
Private Sub Form1_Activated(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Activated Me.Show() LoadSettings() MakeFile() End Sub
Private Function MakeFile() Dim di As New DirectoryInfo(Path1) Dim fiArr As FileInfo() = di.GetFiles()
Dim fil As FileInfo For Each fil In fiArr If fil.Extension = ".dnz" Then ' Check if .coz file exists Dim fInfo As New FileInfo(Path1 & "\" & Replace(fil.Name, ".dnz", ".coz")) Dim fInfo1 As New FileInfo(Path1 & "\" & Replace(fil.Name, ".dnz", ".coz." & AddText)) If Not fInfo.Exists And Not fInfo1.Exists Then ' Check if .dnz.tmp file exists Dim fInfo2 As New FileInfo(Path1 & "\" & Replace(fil.Name, ".dnz", ".dnz.tmp")) If fInfo2.Exists Then ' Check if create time of file is > NOW - WaitTime If DateDiff(DateInterval.Minute, fil.CreationTime, DateAdd(DateInterval.Minute, -WaitTime, Now)) > WaitTime Then ' Check if last write time of file is > NOW - WaitTime If DateDiff(DateInterval.Minute, fil.LastWriteTime, DateAdd(DateInterval.Minute, -WaitTime, Now)) > WaitTime Then ' Only convert file if it is not older than 1 day If DateDiff(DateInterval.Hour, fil.CreationTime, Now) < 24 Then
Dim pInfo As New ProcessStartInfo() Dim p As Process = Process.Start(PathConverter, "Convert """ & Path1 & "\" & fil.Name & """ """ & Path1 & "\" & Replace(fil.Name, ".dnz", ".coz.") & AddText & "")
Do While Not p.HasExited ' The last process is still running Threading.Thread.Sleep(1000) Application.DoEvents() Loop
' Rename file when the above process is done My.Computer.FileSystem.RenameFile(Path1 & "\" & Replace(fil.Name, ".dnz", ".coz.") & AddText, Replace(fil.Name, ".dnz", ".coz")) ConvertedCounter = ConvertedCounter + 1 End If End If End If End If End If End If Next fil
For i = 1 To 10 Threading.Thread.Sleep(1000) Application.DoEvents() Next MakeFile() End Function End Class
Opklarende spørgsmål - hvorfor kalder du MakeFile rekursivt? Ville måske være mindre hukommelseslugende at kalde den gentagent udefra i en løkke... Fx (ikke testet):
Private Sub Form1_Activated(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Activated Me.Show() LoadSettings() Do While True MakeFile() Application.DoEvents() Threading.Thread.Sleep(1000) Loop End Sub
Godt spørgsmål, det havde jeg ikke lige tænkt på. Jeg har nu lavet den om som du foreslår så ser jeg om den stadig går ned. Men jeg tror ikke det er pga. hukommelse mangel for computeren jeg tester programmet på har 24 GB og jeg har aldrig set mit program bruge mere end ca. 100 mb.
Det kommer an på hvor meget hukommelse programmet får tildelt - ikke hvor meget hukommelse der er på maskinen. Og da de rekursive kald aldrig returnerer, vil hukommelsesforbruget jo være støt stigende, da hvert kald lægger en klat data på stakken.
Hvis jeg bruger din løsning med at lave en loop i min Form1_Activated, kender du så en måde hvorpå jeg kan have min MakeFile funktion kørende samtidigt på flere kerner, eks:
Kerne1: Do While True MakeFile(Parameter1) Application.DoEvents() Threading.Thread.Sleep(1000) Loop
Kerne2: Do While True MakeFile(Parameter2) Application.DoEvents() Threading.Thread.Sleep(1000) Loop
Hmm, tror ikke jeg helt forstår dit begreb 'kerner'... :-)
Hvis du ønsker at overvåge 2 mapper og argumentet til MakeFile er stien til mappen, ku du vel bare kalde dem efterfølgende i samme loop:
Do While True MakeFile(Parameter1) MakeFile(Parameter2) Application.DoEvents() Threading.Thread.Sleep(1000) Loop
Hvis de skal køre i hver sin tråd, ku du evt. starte programmet 2 gange med hver sin mappeparameter. Eller starte løkkerne i hver sin tråd i programmet...
Ja, det er korrekt at jeg vil overvåge 2 mapper og derfor have dem til at køre på hver sin tråd. Jeg vil helst undgå at starte programmet 2 gange og er derfor interesseret i at have løkkerne kørende i hver sin tråd i programmet. Kan du hjælpe med hvordan det gøres?
Jeg vil gerne have at de køre samtidigt og dermed udnytter flere af computerens ressourcer. Den konvertering jeg laver kan tage omkring en time pr. fil og så vil det være træls at den først kigger mappe 2 igennem når den har været alle filer i mappen 1 igennem.
Jeg har ikke prøvet at lave flere tråde i VB, men mon ikke noget lignende det nedenstående kan gøre det? (Stadig ikke testet ;-) ):
Private parm As String
Private Sub InitiateThreads() Me.parm = "<sti til mappe1>" Dim t1 As New Thread(AddressOf DoWork) t1.Start() Me.parm = "<sti til mappe2>" Dim t2 As New Thread(AddressOf DoWork) t2.Start() End Sub
Private Sub DoWork() Dim path As String = Me.parm Do While True MakeFile(path) Application.DoEvents() Threading.Thread.Sleep(1000) Loop End Sub
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.