如何延迟 vb.net 程序直到文件操作完成?

发布于 2024-07-11 20:47:36 字数 408 浏览 9 评论 0原文

我有这个:

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

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

优雅的叶子 2024-07-18 20:47:37

我对 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)

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)
家住魔仙堡 2024-07-18 20:47:37

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

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.

慢慢从新开始 2024-07-18 20:47:37

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

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

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

踏月而来 2024-07-18 20:47:37

这很丑,但对我有用

 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 

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 
っ左 2024-07-18 20:47:37

这有点 hacky,但应该可以。

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

This is a bit hacky, but it should work.

Do Until (System.IO.File.Exists("C:\" & myTemp))
    Threading.Thread.Sleep(1)
Loop
自找没趣 2024-07-18 20:47:37

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

尝试这样做来制作代码块的关键部分:

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

OpenFile(myTemp)

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)
思慕 2024-07-18 20:47:37

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

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

宫墨修音 2024-07-18 20:47:37

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

也就是说,Copy 方法是一个同步操作。 在对 Copy 的调用完成之前,不会发生对 OpenFile 的调用。

也就是说,当调用 OpenFile 时,如果该文件不存在,那是因为您将其复制到了错误的位置,或者因为某些其他进程正在处理相关文件。

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.

世界如花海般美丽 2024-07-18 20:47:37

我认为同步时钟不适合这种情况的

解释,MSDN可以帮助我

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

在我看来,复制是阻塞方法,因此线程等待复制完成

在另一个地方不会有问题吗?

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?

三生一梦 2024-07-18 20:47:37
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 
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 
擦肩而过的背影 2024-07-18 20:47:37

System.Threading.Thread.Sleep(1000);

System.Threading.Thread.Sleep(1000);

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文