我試圖實現以下目標:如何在.NET中自定義任務調度?
主線程應該創建一些任務(實際上,可能有很多線程,但現在讓我們來簡化事情,以避免額外的與併發和並行的複雜性),這是莫名其妙預定並在稍後執行。也許某些Timer
以固定的時間間隔,可能晚些時候在同一個線程中,當它阻塞這些任務時,可能是通過專門爲此任務指定的另一個線程 - 調度的實現目前還沒有很好定義,我只是試圖瞭解基本的想法。 我希望我的代碼以某種方式是這樣的:
'Somewhere in the main thread...
Dim MyTask = CreateTask(Of Integer)(Function()
Console.WriteLine("Task has been called!")
'Some activity...
Return 42
End Sub)
'...
UseTheResult(MyTask.Result)
...其中CreateTask
響應調度的代表爲以後執行任務的子程序。
事情是,我不知道如何實現這個概念。起初,我試過使用SynchronizationContext
,但它似乎更像是私有線程內存,並且與調度任務無關(儘管Windows UI似乎以某種方式用於此目標 - 我還沒有清楚地理解所有這些背景thingie)。然後我偶然發現了TaskScheduler
,它與TaskFactory
相似,似乎只是做這件事。我試圖使我的這個線程的實現,但我的代碼沒有按預期工作,這意味着我錯過了一些非常重要的事情,如何TaskScheduler
工作,甚至更糟 - 關於這個整體概念。我已經閱讀了一些關於這個主題的文章(最顯着的是,TaskScheduler
上的MSDN documentation及其代碼示例),但仍不明白這是如何工作的。
我不-工作,如預期的代碼,這本來是安排,然後在它們之間具有100ms的延遲執行任務(所以整個測試應該已經運行了〜10秒):
Public Sub Main()
Dim T As New TaskFactory(New TestScheduler)
Dim tasks As New List(Of Task)
For I = 1 To 100
Dim J = I
tasks.Add(T.StartNew(Sub() Console.WriteLine(J)))
Next I
Task.WaitAll(tasks.ToArray)
Console.WriteLine("Test end")
Console.ReadLine()
End Sub
Class TestScheduler : Inherits TaskScheduler
Dim Tasks As New Collections.Concurrent.ConcurrentQueue(Of Task)
'Dim Counter As New Threading.AutoResetEvent(False)
Dim CTimer As New Threading.Timer(AddressOf TimerUp, Nothing, 0, 100)
Protected Overrides Function GetScheduledTasks() As IEnumerable(Of Task)
Return Tasks
End Function
Private Sub TimerUp(State As Object)
Static AllTasks% = 0
Dim T As task = Nothing
If Tasks.TryDequeue(T) Then
Console.WriteLine("Task... {0}", AllTasks) 'for debugging
AllTasks += 1
If Not MyBase.TryExecuteTask(T) Then
QueueTask(T)
End If
End If
End Sub
Protected Overrides Sub QueueTask(task As Task)
Tasks.Enqueue(task)
End Sub
Protected Overrides Function TryExecuteTaskInline(task As Task, taskWasPreviouslyQueued As Boolean) As Boolean
If taskWasPreviouslyQueued Then Return False
Return MyBase.TryExecuteTask(task)
End Function
End Class
'Output:
'2
'1
'2
'... and that's it, no even "Test end" or any other output whatsoever.
'I have strong feeling that it throws an exception somewhere; however,
'when I try to debug it, it silently stops, without waiting for <Enter>,
'and when I run it without debugging - it produces the abovementioned output without
'any exceptions or messages.
我有很強烈的感覺,我誤解了這裏的一些基本概念。
因此,總結一下,我的問題是:如何自定義.NET中的任務調度?
我應該使用什麼 - SynchronizationContext
,TaskScheduler
,派生類或其他東西?如果是這樣,我應該覆蓋哪些確切的方法,它們的含義是什麼?所有這些QueueTask
,TryExecuteTaskInline
和TryExecuteTask
只是纏着我瘋了...
P.S:請原諒,如果你願意的話,糾正任何語法或邏輯錯誤,我做了那裏。英語不是我的本地人,現在我沒有想太清楚[睡着了]。謝謝!
編輯:我很抱歉誤導你,大家。該代碼正在工作完美無缺,我剛剛犯了一個非常粗略的錯誤,忘記將我的項目標記爲「啓動」 - 並且意外地在同一解決方案中運行另一個測試項目......起初,我要去爲了解決這個問題,但後來我意識到最好能夠回答它 - 它應該幫助有同樣問題的人,最重要的是,允許有更好的解決方案:到目前爲止還有很多問題沒有得到解答。爲什麼我們需要TaskScheduler.TryExecuteTask
- 爲什麼「嘗試」,到底是什麼?什麼時候該方法可以返回False
? TryExecuteTaskInline
方法何時運行,以及何時可以執行taskWasPreviouslyQueued = true
?我有一些假設,但是,他們也可能是錯的。
我是否需要將這些主題作爲單獨的問題提出,或者由於它們仍然屬於這個問題的標題,它們可以在那裏很好嗎?
你使用過'Semaphore'類或SemaphoreSlim嗎? –
我有點困惑。 'Semaphore'類應該如何提供幫助?據我所知,它與任務調度無關。 – DeFazer