我正在 vb.net 中开始一项新任务并等待一段时间。如果到那个时候任务没有完成,我不想附加另一个任务作为延续,并且在另一个任务日志中已经过了 task1 的执行时间。代码或多或少看起来像这样:
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 任务将作为延续附加到它。
这会产生这样的日志:
Task Timeoud!超时时间:10000 毫秒,经过时间:3371 毫秒
我有异常记录等,可以确认没有异常和错误。似乎只是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 多个任务)。