3

我有这个:

    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() 会纠正这个问题,但事实并非如此。在打开文件之前,我需要等到文件创建完成。我怎样才能做到这一点?

4

11 回答 11

3

我真的不太了解 VB.NET,但 Copy 不是阻塞调用吗?你确定你不只是试图从错误的位置打开文件(或者未转义的反斜杠使路径无效)?

那这个呢?我已将驱动器号添加到 OpenFile,并在两个地方都转义了反斜杠。

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

System.IO.File.Copy(myFile, "c:\\" & myTemp)
OpenFile("c:\\" & myTemp)
于 2009-01-12T23:32:15.867 回答
1

理想情况下,您应该在一个单独的线程上执行复制,该线程在完成时通知主 GUI 线程,以便它可以通过 Invoke 调用执行打开。

于 2009-01-12T23:24:48.643 回答
1

使用 FileSystemWatcher 在创建文件时提醒您。没有循环。

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

于 2011-01-01T21:24:47.127 回答
1

这很难看,但对我有用

 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 
于 2014-07-22T15:46:00.463 回答
0

这有点hacky,但它应该可以工作。

Do Until (System.IO.File.Exists("C:\" & myTemp))
    Threading.Thread.Sleep(1)
Loop
于 2009-01-12T23:21:40.880 回答
0

这并不是 Doevents 的真正用途。它最常用于让 UI 消息队列清空(让 UI 有一些 CPU 时间来刷新)。它比我描述的要复杂一些,但这不是你问题的重点,所以我将继续。

试试这个来制作代码块的关键部分:

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

OpenFile(myTemp)
于 2009-01-12T23:24:44.977 回答
0

除了汤姆的回答之外,放置一个 Application.DoEvents() 而不是让线程休眠不是更好吗?

于 2009-01-12T23:35:01.807 回答
0

首先,您不应该在任何地方调用 DoEvents。在大多数情况下,当它被使用时,它是一种绕过真正应该是异步操作的技巧。

话虽如此,该Copy方法是同步操作。在调用完成OpenFile之前不会发生调用Copy

话虽如此,当调用OpenFile发生时,如果文件不存在,那是因为您将其复制到了错误的位置,或者因为其他进程正在处理相关文件。

于 2009-01-13T01:29:31.683 回答
0

我觉得 Synclock 不适合这种情况

为了解释,MSDN可以帮助我

SyncLock 语句确保多个线程不会同时执行相同的语句。当线程到达 SyncLock 块时,它会计算表达式并保持这种排他性,直到它锁定表达式返回的对象。这可以防止表达式在多个线程运行期间更改值,这可能会从您的代码中产生意外的结果。

在我看来,复制是阻塞方法,所以线程一直等到复制完成

在其他地方不会有问题吗?

于 2009-01-13T09:07:32.447 回答
0
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 
于 2010-03-09T17:51:08.683 回答
-1

System.Threading.Thread.Sleep(1000);

于 2009-01-12T23:17:19.297 回答