Как мне задержать программу vb.net до завершения операции с файлом?

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

  •  22-07-2019
  •  | 
  •  

Вопрос

У меня есть это:

    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);

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top