2013-08-30 66 views
4

我正在vb.net中启动一个新任务并等待一段时间。如果到那时任务没有完成,我不想将另一个任务作为延续,并且在任务1的执行的另一个任务日志执行时间内。代码看起来像或多或少:Task.Wait不会等待

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)随机决定不要等待...
任何人都来过这个问题吗?有没有解决方案?谢谢你的时间。

---- ----编辑

好了,所以我也加入了秒表和outputing东西调试做过一个实验:

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开始的内部(SWE前失效开始)。
所以我发现TaskFactory.StartNew()并不总是立即启动任务,如果线程池满了,任务将被放入队列中。虽然这是可以理解的,但Task.Wait()显然没有考虑到这一点,所以任务可能在等待结束后开始。我正在阅读有关TaskScheduler的内容,以检查是否可以增加线程池以适应所有任务,或者采取其他措施解决问题(但我不知道现在是嘿嘿)如果你们有任何想法,请让我知道:)

---- ----编辑

为您女士和gentelmen另一个更新。线程池填充问题已经通过暗示创建新任务​​来解决(最初)。根据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

'timeout'是一个常数还是可能会被更新?另外,如何计算'elapsedTime'? –

+0

timeout是一个从配置文件中取出的变量(它在代码中的任何地方都没有更新)。 elapsedTime从_GetAvailability()中的秒表中拉出并分配给类变量 –

+1

一个类变量,你说。它的价值可能被其他任务覆盖吗? –

回答

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) 

应至少理清报表的问题。

+0

Touple的好主意,谢谢:) –