Как мне задержать программу vb.net до завершения операции с файлом?
Вопрос
У меня есть это:
Dim myTemp As String
myTemp = System.DateTime.Now().ToString("MMMddyyyy_HHmmss") & ".pdf"
System.IO.File.Copy(myFile, "c:\" & myTemp)
Application.DoEvents()
OpenFile(myTemp)
Проблема в том, что когда я вызываю OpenFile, который представляет собой просто вызов подпрограммы, открывающей файл, он не может найти файл.Это связано с тем, что он вызывает его так быстро, что программа не успевает создать файл до того, как произойдет его открытие.
Я думал, что DoEvents() исправит это, но это не так.Мне нужно подождать, пока файл будет создан, прежде чем открывать его.Как мне это сделать?
Решение
Я не очень хорошо знаю VB.NET, но не копирую ли блокирующий вызов? Вы уверены, что не просто пытаетесь открыть файл не в том месте (или обратный слеш без экранирования делает путь недействительным)?
Как насчет этого? Я добавил букву диска в OpenFile и избежал обратной косой черты в обоих местах.
Dim myTemp As String
myTemp = System.DateTime.Now().ToString("MMMddyyyy_HHmmss") & ".pdf"
System.IO.File.Copy(myFile, "c:\\" & myTemp)
OpenFile("c:\\" & myTemp)
Другие советы
В идеале вы должны выполнить копирование в отдельном потоке, который информирует основной поток GUI, когда это будет сделано, чтобы он мог затем выполнить открытие через вызов Invoke. Р>
Используйте FileSystemWatcher, чтобы предупредить вас о создании файла. Без петель.
https: //web.archive.org/web/1/http://articles.techrepublic%2ecom%2ecom/5100-10878_11-6165137.html р>
Это некрасиво, но у меня это работает
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
Это немного глупо, но это должно сработать.
Do Until (System.IO.File.Exists("C:\" & myTemp))
Threading.Thread.Sleep(1)
Loop
Это не совсем то, для чего используется Doevents. Чаще всего он используется для очистки очереди сообщений пользовательского интерфейса (чтобы пользовательский интерфейс имел некоторое время ЦП для обновления). Это немного сложнее, чем я описываю, но не в этом суть вашего вопроса, поэтому я буду двигаться дальше.
Попробуйте создать критическую секцию вашего блока кода:
SyncLock Me
System.IO.File.Copy(myFile, "c:\" & myTemp)
Application.DoEvents()
End SyncLock
OpenFile(myTemp)
В дополнение к ответу Тома, не лучше ли поставить Application.DoEvents (), а не заставлять поток спать?
Во-первых, вы не должны нигде вызывать DoEvents. По большей части, когда это используется, это хак, чтобы обойти то, что действительно должно быть асинхронной операцией.
При этом метод Copy
является операцией синхронный . Вызов OpenFile
не будет выполнен до тех пор, пока не будет завершен вызов Copy
.
Это, как говорится, когда происходит вызов OpenFile
, если файл не существует, это потому, что вы скопировали его в неправильное место или потому, что какой-то другой процесс работает с данным файлом . р>
Я думаю, что Synclock не подходит для этого случая
для объяснения, MSDN может помочь мне
Оператор SyncLock гарантирует, что несколько потоков не будут выполнять одни и те же операторы одновременно. Когда поток достигает блока SyncLock, он оценивает выражение и поддерживает эту исключительность до тех пор, пока не получит блокировку объекта, возвращаемого выражением. Это не позволяет выражению изменять значения во время работы нескольких потоков, что может дать неожиданные результаты из вашего кода. Р>
по моему мнению, копирование является методом блокировки, поэтому поток ожидает, пока копирование не будет выполнено
не может быть проблемой в другом месте?
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);