Vb.net 如何在不使用大量CPU的情况下连续循环

Vb.net 如何在不使用大量CPU的情况下连续循环,vb.net,loops,cpu-usage,Vb.net,Loops,Cpu Usage,我有一个应用程序,它运行一个任务,检查目录中的文件,并在将文件添加到目录时完成。下面是一个简化的示例: Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click Dim addedFile = Await Task.Factory.StartNew(New Func(Of FileInfo)( Function() Dim di =

我有一个应用程序,它运行一个任务,检查目录中的文件,并在将文件添加到目录时完成。下面是一个简化的示例:

Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim addedFile = Await Task.Factory.StartNew(New Func(Of FileInfo)(
        Function()
            Dim di = New DirectoryInfo("C:\_Temporary\Test")

            Do While True
                Dim files = di.GetFiles()

                If (files.Count > 0) Then
                    Return files(0)
                End If
            Loop
        End Function))

    MsgBox(addedFile.FullName)
End Sub
我遗漏了多余的细节,如取消代币等

问题是,当代码运行时,CPU保持稳定在12%左右。即使我注释掉while循环中的主体,它仍然保持不变

我如何创建一个循环机制,这是非等待操作(如等待文件到达目录)所必需的,而不使用那么多CPU

注意:问题不在于涉及文件系统的具体案例;它通常循环不可等待的操作以及对CPU的影响。


相比之下,Windows事件消息循环占用的空间不到1%——例如,如果我在单击运行上述代码的“Button1”之前查看应用程序的CPU使用情况。

使用Filewatcher类在目录更改时接收事件:


使用Filewatcher类在目录更改时接收事件:


使用Filewatcher类在目录更改时接收事件:


使用Filewatcher类在目录更改时接收事件:


因此,最好每秒检查一次文件(但不要使用
While True
循环,始终避免使用它们)

MSDN:


注意:
RepeatingFunction
必须重新响应。还有
Threading.Timer
构造函数的最后一个参数,它会代表滴答之间的间隔。

因此,最好每秒检查一次文件(但是不要使用
While True
循环,始终避免它们)

MSDN:


注意:
RepeatingFunction
必须重新响应。还有
Threading.Timer
构造函数的最后一个参数,它会代表滴答之间的间隔。

因此,最好每秒检查一次文件(但是不要使用
While True
循环,始终避免它们)

MSDN:


注意:
RepeatingFunction
必须重新响应。还有
Threading.Timer
构造函数的最后一个参数,它会代表滴答之间的间隔。

因此,最好每秒检查一次文件(但是不要使用
While True
循环,始终避免它们)

MSDN:


注意:
RepeatingFunction
必须重新响应。另外,
Threading.Timer
constructor的最后一个参数也会表示滴答声之间的间隔。

您正在轮询。投票从来都不是一个好主意,原因有很多。轮询在软件中非常常见,即使是在一些知名的商业软件中,也会保持匿名。正如您已经知道的那样,它会导致一系列问题,从不必要地占用处理器,到阻止处理器睡眠,以及导致电池耗尽速度比其他情况更快

解决方案#1:最理想的解决方案是像其他人指出的那样找到一个内置的观察者。在幕后,观察者可能正在使用特定的中断机制或使用内核定时例程来模拟中断

解决方案#2:如果不存在这样的监视程序,可以使用带有sleep()的for/while循环每隔这么多秒检查一次:它检查,进入睡眠状态一段时间,然后再次检查。sleep()函数不会使用任何处理时间(不完全正确,但实际上是这样)

即使使用解决方案#2,您也可能会陷入一些陷阱,这将导致您使用比需要更多的处理。对你需要多久检查一次身体状况做一次现实的分析。一个非常常见的错误是在错误的假设下设置了一个非常短的轮询周期,即应用程序的响应速度会更快

如果您的典型事件每隔一两分钟发生一次,并且您需要在5秒内对事件做出反应,那么10毫秒的轮询时间并不能换来任何收益,也会损害每个人的绩效。在这种情况下,您可以每2秒进行一次轮询,这比10毫秒的轮询频率少了近三个数量级


许多人不知道的另一件事是,在典型的操作系统(如Linux和Windows)中,计时器等的基本分辨率约为10毫秒,即使数据结构允许您以微秒为单位进行指定。

您正在轮询。投票从来都不是一个好主意,原因有很多。轮询在软件中非常常见,即使是在一些知名的商业软件中,也会保持匿名。正如您已经知道的那样,它会导致一系列问题,从不必要地占用处理器,到阻止处理器睡眠,以及导致电池耗尽速度比其他情况更快

解决方案#1:最理想的解决方案是像其他人指出的那样找到一个内置的观察者。在幕后,观察者可能正在使用特定的中断机制或使用内核定时例程来模拟中断

解决方案#2:如果不存在这样的监视程序,可以使用带有sleep()的for/while循环每隔这么多秒检查一次:它检查,进入睡眠状态一段时间,然后再次检查。sleep()函数不会使用任何处理时间(不完全正确,但实际上是这样)

即使使用解决方案#2,您也可能会陷入一些陷阱,这将导致您使用比需要更多的处理。对你需要多久检查一次身体状况做一次现实的分析。一个非常常见的错误是在错误的假设下设置了一个非常短的轮询周期,即应用程序的响应速度会更快

如果您的典型事件每隔一两分钟发生一次,并且您需要在5秒内对事件做出反应,那么10毫秒的轮询时间并不能换来任何收益,也会损害每个人的绩效。在这种情况下,您可以每2秒进行一次轮询,这比10毫秒的轮询频率少了近三个数量级

另一件很多人没有意识到的事情是t
' Create a new FileSystemWatcher and set its properties. 
Dim watcher As New FileSystemWatcher()
watcher.Path = "C:\_Temporary\Test"
' Watch for changes in LastAccess and LastWrite times, and 
' the renaming of files or directories. 
watcher.NotifyFilter = (NotifyFilters.LastAccess Or NotifyFilters.LastWrite Or NotifyFilters.FileName Or NotifyFilters.DirectoryName)
' Only watch text files.
watcher.Filter = "*.txt" 

' Add event handlers. 
AddHandler watcher.Created, AddressOf OnChanged

' Define the event handlers. 
Private Shared Sub OnChanged(source As Object, e As FileSystemEventArgs)
   ' Specify what is done when a file is changed, created, or deleted.
   MsgBox(e.FullPath)
End Sub     
Dim timerDelegate As TimerCallback = AddressOf RepeatingFunction
Dim autoEvent As New AutoResetEvent(True)
Dim dt As New System.Threading.Timer(timerDelegate, autoEvent, 0, 1000)