我要在VB.NET中开始一个新的任务,并等待一段时间。如果在那段时间内任务未完成,我希望附加另一个任务作为续接,并在其中记录任务1执行的经过时间。代码看起来大致如下:
Dim task As Task(Of Availability) = task.Factory.StartNew(
Function() As Availability
Return _GetAvailability(requests)
End Function)
task.Wait(timeout)
If task.IsCompleted Then
MyBase.availability = task.Result
Else
task.ContinueWith(Sub(previous)
LogAvailabilityTimeout(timeout, elapsedTime)
End Sub, TaskContinuationOptions.OnlyOnRanToCompletion)
End If
由于某种原因,偶尔的
task.Wait(timeout)
不会按照指定的时间等待,而是直接跳过。由于此时任务未完成,因此将LogAvailabilityTimeout任务作为其继续任务附加到它。这会导致类似以下的日志:
任务超时! 超时时间:10000ms,已用时间:3371ms
我已经设置了异常记录等,并确认没有异常和错误。看起来只是
task.Wait(timeout)
随机决定不等待...有人遇到过这种情况吗? 有什么解决方法吗? 感谢您的时间。
---- 编辑 ----
好的,所以我做了一个实验,添加了一个秒表并将一些内容输出到调试中:
Dim swTemp As StopWatch = StopWatch.StartNew()
Dim task As Task(Of Availability) = task.Factory.StartNew(
Function() As Availability
Return _GetAvailability(requests)
End Function)
task.Wait(timeout)
swTemp.Stop()
Debug.WriteLine("Waited For: " & swTemp.ElapsedMilliseconds)
If task.IsCompleted Then
MyBase.availability = task.Result
Else
task.ContinueWith(Sub(previous)
LogAvailabilityTimeout(timeout, elapsedTime)
End Sub, TaskContinuationOptions.OnlyOnRanToCompletion)
End If
_GetAvailability
看起来大致如下:
Private Function _GetAvailability(requests As RequestsCollection) As Availability
Dim swElapsed As New StopWatch = StopWatch.StartNew()
'do some stuff here (CPU heavy and network related)
swElapsed.Stop()
Debug.WriteLine("Elapsed: " & swElapsed.ElapsedMilliseconds)
Me.elapsedTime = swElapsed.ElapsedMilliseconds
Return xxx
End Function
看起来它确实在等待10000,但是在
_GetAvailability
内部开始之前存在大延迟(swElapsed开始)。因此我发现
TaskFactory.StartNew()
并不总是立即启动任务,如果线程池已满,则任务将被放入队列中。虽然这可以理解,但Task.Wait()
显然没有考虑到这一点,因此任务可能在等待完成后才开始。我正在阅读关于TaskScheduler的内容,以查看是否可以增加线程池以适应所有任务,或者做其他事情来解决问题(但目前我还不知道是什么)...如果你们有任何想法,请让我知道:)
----编辑----
为女士们和先生们提供另一个更新。线程池填充的问题已通过使用TaskCreationOptions.LongRunning
提示新任务创建进行了解决。根据MS文档介绍,这提示TaskScheduler任务可能会阻塞线程池更长的时间,在这种情况下,调度程序会创建额外的线程来容纳它。这就是我现在如何触发任务的方式:
Dim task As Task(Of Availability) = task.Factory.StartNew(
Function() As Availability
Return _GetAvailability(requests)
End Function, TaskCreationOptions.LongRunning)
task.Wait(timeout)
自从这个变化以后,所有的任务似乎都在启动时执行(没有被放入队列)。这是在我执行大约50个任务的测试中发现的。现在我要进行更多的负载测试(1000+个任务)。
Wait()
时,没有保证任务已经开始,而你提供的超时时间是当前线程愿意等待的时间,而不是应该给予任务的时间。 - Damien_The_Unbeliever