使用返回 Task
的 Function
,而不是 Async Sub
的主要原因有两个。第一个原因是异常处理。如果你像下面这样做,将会得到一个未捕获的异常,导致应用程序终止:
Public Sub Main()
Try
DoSomethingAsync()
Catch ex As Exception
Console.WriteLine(ex)
End Try
End Sub
Private Async Sub DoSomethingAsync()
Throw New Exception()
End Sub
由于异常是在单独的线程上抛出的,因此 Try/Catch 块无法捕获它。
但是,如果使用以下代码,则可以捕获和处理异常:
Public Async Sub Main()
Try
Await DoSomethingAsync()
Catch ex As Exception
Console.WriteLine(ex)
End Try
End Sub
Private Async Function DoSomethingAsync() As Task
Throw New Exception()
End Sub
第二个重要原因是,即使你现在不需要它,将来你可能会需要。如果它已经是一个返回任务的函数,那么你可以随意使用它。如果不是,则无法对其进行等待、安排后续操作、中止或执行其他任务。所以,问题实际上不是“为什么这样做?”,而是“为什么不这样做呢?”
例如,以下代码将输出“Here”,然后是“Done”:
Public Sub Main()
DoSomethingAsync()
Threading.Thread.Sleep(5000)
Console.WriteLine("Done")
End Sub
Public Async Function DoSomethingAsync() As Task
Console.WriteLine("Here")
End Function
正如其他人提到的那样,为了避免警告,您可以像这样将任务分配给变量:
Public Sub Main()
Dim t As Task = DoSomethingAsync()
Threading.Thread.Sleep(5000)
Console.WriteLine("Done")
End Sub
这两种方式的工作方式相同,并且在其自己的线程上运行,就像 Async Sub
一样。即使 Task
变量超出了范围,也不会影响任务继续运行。例如:
Public Sub Main()
DoSomething()
Threading.Thread.Sleep(5000)
Console.WriteLine("Really Done")
End Sub
Public Sub DoSomething()
Dim t As Task = DoSomethingAsync()
Console.WriteLine("Done Doing Something")
End Sub
Public Async Function DoSomethingAsync() As Task
Console.WriteLine("Here")
End Function
Async Sub
仅用于事件处理程序。如果它确实是一个事件处理程序,则应该使用Async Sub
,但事件处理程序还应具有适当的参数。如果不是事件处理程序,则不应该使用Async Sub
。 - jmcilhinney