How do I delay a vb.net program until a file opera

2019-07-04 02:41发布

问题:

I have this:

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

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

The problem is that when I call OpenFile, which is just a call to a sub that opens a file, it cannot find the file. This is because it is calling it so quickly that the program doesn't have time to actually create the file before the open takes place.

I thought that DoEvents() would rectify this but it does not. I need to wait until the file is created before I open the file. How can I do that?

回答1:

I don't really know much VB.NET, but isn't Copy a blocking call? Are you sure you're not just trying to open the file from the wrong location (or the unescaped backslash invalidates the path)?

What about this? I've added the drive letter to OpenFile, and escaped the backslash both places.

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

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


回答2:

Ideally you should perform the copy on a separate thread that informs the main GUI thread when it is done so it can then perform the open through an Invoke call.



回答3:

Use FileSystemWatcher to alert you when the file is created. No loops.

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



回答4:

This is ugly but it works for 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 


回答5:

This is a bit hacky, but it should work.

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


回答6:

That isn't really what Doevents is used for. It is most frequently used to let the UI message queue clear out (let the UI have some CPU time to refresh). It is slightly more complex than I am describing, but that isn't the point of your question so I will move on.

Try this to make the critical section of your code block:

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

OpenFile(myTemp)


回答7:

In addition to Tom's answer, isnt it better to put a Application.DoEvents() rather then making the thread sleep?



回答8:

First, you should not call DoEvents anywhere. For the most part, when it is used, it is a hack to circumvent what should really be an asynchronous operation.

That being said, the Copy method is a synchronous operation. The call to OpenFile will not occur until the call to Copy completes.

That being said when the call to OpenFile occurs, if the file does not exist, it is because you copied it to the wrong place, or because some other process is working on the file in question.



回答9:

I thinf Synclock is not good for this case

for explaination, MSDN can help me

The SyncLock statement ensures that multiple threads do not execute the same statements at the same time. When the thread reaches the SyncLock block, it evaluates the expression and maintains this exclusivity until it has a lock on the object that is returned by the expression. This prevents an expression from changing values during the running of several threads, which can give unexpected results from your code.

in my opinion, copy is blocking method, so thread waits until copying is done

can`t be problem in another place?



回答10:

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 


回答11:

System.Threading.Thread.Sleep(1000);