我正致力于将使用线程的旧代码替换为基于.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