我在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任务将作为continuation附加到它。
这导致如下日志:
任务Timeoud!超时时间: 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多个任务)。
答案 0 :(得分:1)
您可以按如下方式更改您的功能:
Private Function _GetAvailability(requests As RequestsCollection) As Tuple(Of Availability, Long)
Dim swElapsed As New StopWatch = StopWatch.StartNew()
'do some stuff here (CPU heavy and network related)
swElapsed.Stop()
Debug.WriteLine("Elapsed: " & swElapsed.ElapsedMilliseconds)
Return Tuple.Create(xxx,swElapsed.ElapsedMilliseconds)
End Function
然后总是附加你的延续方法:
task.ContinueWith(Sub(previous)
If previous.Item2 > timeout
LogAvailabilityTimeout(timeout, previous.Item2)
End If
End Sub, TaskContinuationOptions.OnlyOnRanToCompletion)
哪个至少应该解决您的报告问题。