Come ritardare un programma vb.net fino al completamento di un'operazione sui file?

StackOverflow https://stackoverflow.com/questions/437396

  •  22-07-2019
  •  | 
  •  

Domanda

Ho questo:

    Dim myTemp As String
    myTemp = System.DateTime.Now().ToString("MMMddyyyy_HHmmss") & ".pdf"

    System.IO.File.Copy(myFile, "c:\" & myTemp)
    Application.DoEvents()
    OpenFile(myTemp)

Il problema è che quando chiamo OpenFile, che è solo una chiamata a un sub che apre un file, non riesce a trovare il file. Questo perché lo chiama così rapidamente che il programma non ha il tempo di creare effettivamente il file prima che avvenga l'apertura.

Ho pensato che DoEvents () avrebbe rettificato questo, ma non è così. Devo attendere fino alla creazione del file prima di aprire il file. Come posso farlo?

È stato utile?

Soluzione

Non conosco molto VB.NET, ma Copia non è una chiamata bloccante? Sei sicuro di non voler solo aprire il file da una posizione errata (o la barra rovesciata senza caratteri invalida il percorso)?

Che dire di questo? Ho aggiunto la lettera di unità a OpenFile e ho evitato la barra rovesciata in entrambi i punti.

Dim myTemp As String
myTemp = System.DateTime.Now().ToString("MMMddyyyy_HHmmss") & ".pdf"

System.IO.File.Copy(myFile, "c:\\" & myTemp)
OpenFile("c:\\" & myTemp)

Altri suggerimenti

Idealmente dovresti eseguire la copia su un thread separato che informa il thread della GUI principale quando viene fatto in modo che possa quindi eseguire l'apertura tramite una chiamata Invoke.

Usa FileSystemWatcher per avvisarti quando il file viene creato. Nessun loop.

https: //web.archive.org/web/1/http://articles.techrepublic%2ecom%2ecom/5100-10878_11-6165137.html

Questo è brutto ma funziona per me

 Function WaitForFile(fullPath, wdelay)
    Dim vd_start As Date
    vd_start = Now()
    Dim vd_end As Date
    Dim wsec, wmin, whour, wt5string As Integer
    Dim wtstring As String
    Dim count As Integer
    Dim wscale As Integer
    Dim vd_1 As Date
    Dim Vo_fileinfo As FileInfo

    Dim fs As FileStream

    wsec = Format(wdelay Mod 60, "00")
    wmin = Format(Int(wdelay / 60), "00")
    whour = Format(Int(wdelay / (60 * 60)), "00")
    wtstring = CStr(whour) + ":" + CStr(wmin) + ":" + CStr(wsec)
    Dim duration = New System.TimeSpan(0, whour, wmin, wsec)
    vd_end = vd_start.Add(duration)

    On Error GoTo error1
    Dim vsize1, vsize2 As Long
    While vd_start < vd_end
        fs = New FileStream(fullPath, FileMode.Open)
        fs.ReadByte()
        fs.Seek(0, SeekOrigin.Begin)
        fs.Close()
        Vo_fileinfo = New FileInfo(fullPath)
        vsize1 = Vo_fileinfo.Length
        Threading.Thread.Sleep(500)
        Vo_fileinfo = New FileInfo(fullPath)
        vsize2 = Vo_fileinfo.Length
        If vsize1 <> vsize2 Then GoTo error1
        GoTo finalgoto
error1:
        Err.Clear()
        vd_start = Now()
    End While

    WaitForFile = False
    GoTo Endgoto
finalgoto: WaitForFile = True
Endgoto:
End Function 

Questo è un po 'confuso, ma dovrebbe funzionare.

Do Until (System.IO.File.Exists("C:\" & myTemp))
    Threading.Thread.Sleep(1)
Loop

Questo non è davvero ciò per cui Doevents è utilizzato. Viene utilizzato più frequentemente per far svuotare la coda dei messaggi dell'interfaccia utente (consentire all'UI di avere un po 'di tempo di aggiornamento della CPU). È leggermente più complesso di quello che sto descrivendo, ma non è questo il punto della tua domanda, quindi andrò avanti.

Prova questo per rendere la sezione critica del tuo blocco di codice:

SyncLock Me
  System.IO.File.Copy(myFile, "c:\" & myTemp)
  Application.DoEvents()
End SyncLock

OpenFile(myTemp)

Oltre alla risposta di Tom, non è meglio mettere un Application.DoEvents () piuttosto che far dormire il thread?

Innanzitutto, non dovresti chiamare DoEvents da nessuna parte. Per la maggior parte, quando viene utilizzato, è un hack aggirare quella che dovrebbe essere davvero un'operazione asincrona.

Detto questo, il metodo Copia è un'operazione sincrona . La chiamata a OpenFile non verrà eseguita fino al completamento della chiamata a Copia .

Detto questo quando si verifica la chiamata a OpenFile , se il file non esiste, è perché l'hai copiato nel posto sbagliato o perché qualche altro processo sta funzionando sul file in questione .

I thinf Synclock non va bene in questo caso

per spiegazione, MSDN può aiutarmi

  

L'istruzione SyncLock garantisce che più thread non eseguano le stesse istruzioni contemporaneamente. Quando il thread raggiunge il blocco SyncLock, valuta l'espressione e mantiene questa esclusività fino a quando non ha un blocco sull'oggetto che viene restituito dall'espressione. Ciò impedisce a un'espressione di modificare i valori durante l'esecuzione di più thread, il che può fornire risultati imprevisti dal codice.

a mio avviso, la copia è un metodo di blocco, quindi il thread attende fino al termine della copia

non può essere un problema in un altro posto?

dim SourceFile as string
dim DestinationFile as string

SourceFile = "c:/archivo.txt"
DestinationFile = "c:/destino/archivo.txt"

If System.IO.File.Exists(SourceFile) = True Then

    System.IO.File.Copy(SourceFile, DestinationFile, True)
    'or
    'My.Computer.FileSystem.CopyFile(SourceFile, DestinationFile, FileIO.UIOption.AllDialogs, FileIO.UICancelOption.DoNothing)

    SourceFile = ""
    DestinationFile = ""

else

    MessageBox.Show("the file don't copy!") 

end if 

System.Threading.Thread.Sleep (1000);

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top