繁体   English   中英

如何在不标记所有异步方法的情况下使用Await Task.Delay?

[英]How can I use Await Task.Delay without labeling all methods Async?

我正在替换基于线程的.NET 4.5基于任务的系统的旧代码。

我已经用Tasks替换了线程,接下来我正在用Await Task.Delay替换Thread.Sleep调用。 我遇到的问题是无法在Synclock部分中调用await,并且现在使用Await Task.Delay的每个方法都需要标记为Async。

我可能可以解决同步锁问题,因为我只有几个这样的块,可以用更好的代码代替。 但是,必须标记每个方法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的正确用法是什么?

您需要等待的方法应该标记为异步,而不是全部。 如果您有一个简单的函数添加Var1 + Var2 ,则使该异步是荒谬的。 话虽这么说,您最终还是使很多事情变得不同步,因为它们调用的内容调用了需要等待的内容。

根据此处的讨论,使用计时器可能会更好,而计时器会导致另一个问题:“ Task.Delay的正确用法是什么?”? 我只使用它,所以我可以等待UI完成其工作。 例如,我调用一个数据库并启动UI转换,以便可能在接下来的1/2秒内逐渐显示屏幕的新部分。 我不想在那1/2秒内填写我的结果,因为它经常会产生抖动的画面,所以我等到完成为止。 最简单的方法是调用数据库,并创建一个延迟,然后使用WhenAll等待最后一个完成。 这通常是我的1/2秒,但有时是数据库。

附带说明,您可以使用异步方法调用同步方法,该方法也将在后台运行。 这是从线程的转换要容易得多,但是由于您已经更改了大部分代码,所以您不想在这里使用它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM