2013-08-30 64 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的好主意,謝謝:) –