我正致力於將使用線程的舊代碼替換爲基於.NET 4.5任務的系統。如何在不標記所有方法異步的情況下使用Await Task.Delay?
我已經用任務替換了線程,接下來我正在用Await Task.Delay取代我的Thread.Sleep調用。我遇到的問題是無法在Synclock部分中調用await,並且現在每個使用Await Task.Delay的方法都需要標記爲Async。
我可以解決synclock問題,因爲我只有幾塊,可以用更好的代碼替換。但是,必須標註每種方法異步正在導致問題。這意味着我必須標記調用方法Async等方法。最終,我所有的方法都將是Async。
這是應該如何做,當使用基於任務的方法,或者我做錯了嗎?
編輯1:過帳示例代碼
Public Async Function Delay(Milliseconds As Integer, Optional Initial As Boolean = False, Optional Silent As Boolean = False, Optional Modifier As Double = 0.3, _
Optional Task As Task = Nothing, Optional ExitOnTaskStop As Boolean = True) As Tasks.Task(Of Boolean)
Dim OutputBufferKey As String = Nothing
If Task IsNot Nothing Then
If Task.StopRequested Then Return True
OutputBufferKey = Task.OutputBufferKey
End If
If Initial Then
Milliseconds = Rand.Next(0, Milliseconds)
ElseIf Modifier > 0 Then
Dim MinValue As Integer = CInt(Milliseconds * (1 - Modifier))
Dim MaxValue As Integer = CInt(Milliseconds * (1 + Modifier))
If MinValue < MaxValue Then Milliseconds = Rand.Next(MinValue, MaxValue + 1)
End If
If DebugMode AndAlso Not Silent Then
Dim LengthString As String = Nothing
Select Case Milliseconds
Case Is < 60 * 1000 : LengthString = Math.Round(Milliseconds/1000, 1) & " seconds"
Case Is < 60 * 60 * 1000 : LengthString = Math.Round(Milliseconds/(60 * 1000), 1) & " minutes"
Case Else : LengthString = Math.Round(Milliseconds/(60 * 60 * 1000), 1) & " hours"
End Select
Output(OutputBufferKey, "Sleeping for " & LengthString)
End If
If ExitOnTaskStop AndAlso Task IsNot Nothing Then
Try
Await Tasks.Task.Delay(Milliseconds, Task.CancellationToken.Token)
Catch ex As OperationCanceledException
Return True
End Try
Else
Await Tasks.Task.Delay(Milliseconds)
End If
Return False
End Function
我需要有很多原因的延遲和調用該方法在許多其它方法。爲了給出幾個例子,我使用OpenPop DLL檢查收件箱是否有郵件到達,如果它沒有在第一次檢查時出現,我需要等待再次檢查之前,我有循環,如果沒有,則有一個睡眠已被發現。另一個例子是我需要做一個HttpWebRequest來檢查一個文件,如果內容沒有改變,我想在30秒內再次做這件事。
我想使用計時器會是一個更好的主意嗎?如果是這樣,Task.Delay的正確用法是什麼?
「我用Tasks替換了線程,接下來我正在用Await Task.Delay替換Thread.Sleep調用。」爲什麼? – Sam 2014-09-10 21:08:26
你爲什麼叫'Thread.Sleep'?如果你在整個代碼的隨機地方使用它,你很可能做錯了。將業務邏輯與任務調度邏輯分開。而且你實際上不需要替換所有'Thread.Sleep'的調用,但這取決於用法。 – Athari 2014-09-10 21:11:37
@Sam我以前的做法是創建數千個線程,我被告知使用任務是更好的方式。至於Thread.Sleep,Task.Delay似乎有所改進,因爲我可以給它取消令牌,所以我不必Thread.Sleep(100),檢查取消並再次循環。這些最近的問題可能會更好地解釋我是如何到達這裏的。 https:// stackoverflow。com/questions/25764970/should-i-use-asynchronous-methods-within-a-background-thread http://stackoverflow.com/questions/25773587/how-do-i-deal-without-byref-in- an-async-function/25773634 – iguanaman 2014-09-10 21:12:40