【问题标题】:Async Sub() Or Async Function() As Task for Fire and Forget?Async Sub() 或 Async Function() 作为 Fire and Forget 的任务?
【发布时间】:2019-07-07 09:27:39
【问题描述】:

我想异步做一些事情,不关心结果。
最好的方法是什么?

Public Async Function HandlerForSomeEvent() As Task
  'This is where I do stuff

  'Then this is stuff I want to do without waiting for it
  DoStuff()

  'Here I continue doing other stuff
End Function
Async Sub DoStuff()
  'Doing stuff while the handler continues doing it's stuff
End Sub

'VS

Async Function DoStuff() As Task
  'Doing stuff while the handler continues doing it's stuff
End Function

每个人都告诉我使用Function As Task,但由于我不等待它,我总是在 VS 中收到烦人的警告。
有什么区别,我为什么要这样做?

【问题讨论】:

标签: vb.net asynchronous async-await task


【解决方案1】:

使用返回Task 而不是Async SubFunction 的主要原因有两个。首先是异常处理。如果你做这样的事情,你会得到一个未捕获的异常,这将终止你的应用程序:

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 SubTask 变量是否超出范围也没关系。即使没有任何东西引用它,该任务也会继续运行。例如:

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

【讨论】:

  • 当我等待它时,我的处理程序会停止。这才是重点。我想同时做这两件事。
  • 您不必等待异步函数。只需将 Task 分配给它返回一个变量,然后您可以稍后使用该变量,例如测试IsFaulted 以查看其中是否引发了异常。
  • @jmcilhinney 问题在于我不能在事件处理程序本身中使用长时间运行的代码。我不能超过 3 秒。异步的东西需要 10 秒以上。当我将任务分配给 var 时,我仍然需要稍后等待它们,对吧?
  • @Fox 不,如果您不等待任务,它仍然会自行运行,就像 Async Sub 一样。等待它是可选的。
  • @jmcilhinney 但是当我分配它并且处理程序在任务之前结束时,var 会被释放,不是吗?
猜你喜欢
  • 2013-11-08
  • 2014-10-20
  • 1970-01-01
  • 2014-08-12
  • 2018-03-01
  • 2020-03-21
  • 2014-05-16
  • 2011-04-04
  • 1970-01-01
相关资源
最近更新 更多