首先,我在这里搜索并看到了许多类似的问题,但没有一个是我想要的。
我的函数需要一些时间来返回一个值 为了简化,我们说它是:
Private Function longProcess() As Boolean
Threading.Thread.Sleep(10000)
Return True
End Function
我想运行它并获得它的值,让我们说点击Button1
我尝试了以下代码并且它运行良好
Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'some stuff
Dim output As Boolean = Await Task.Run(Of Boolean)(Function() longProcess())
'continue another stuff when the longProcess completes
End Sub
如果这种方式足够好?如果没有,它可能有什么问题?
我正在使用另一种方式,但由于 Application.DoEvents()
,它使CPU使用率更高Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'some stuff
Dim awaiter = Task.Run(Of Boolean)(Function() longProcess()).GetAwaiter()
Do While Not awaiter.IsCompleted
Application.DoEvents()
Loop
Dim output As Boolean = awaiter.GetResult()
'continue another stuff when the longProcess completes
End Sub
答案 0 :(得分:4)
根据评论,您的"长期运行"函数发送http请求,你应该使用"完全" Task.Run
Private Async Function SendRequest() As Task(Of Boolean)
Using (client As New HttpClient())
client.BaseAddress = new Uri("http://your:api/")
Dim response As HttpResponseMessage = Await client.GetAsync(pathToResource)
Return response.IsSuccessStatusCode
End Using
End Function
然后点击按钮
Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'some stuff
Dim output As Boolean = Await SendRequest()
'continue another stuff when the longProcess completes
End Sub
上面的方法比使用Task.Run
的方法更好,因为当你从另一个线程发送请求时,该线程什么也不做,只是等待响应。通过使用async-await
(或其他类)的异步HttpClient
方法,整个工作将在一个线程上完成,而不会阻止应用程序的主UI线程。
关于HttpClient
的注意事项:即使在HttpClient
块中使用的Using
实例上面的示例中,您也应该只为应用程序生命周期使用一个实例。
来自Microsoft文档:
HttpClient旨在实例化一次并在整个过程中重复使用 申请的生命。特别是在服务器应用中 为每个请求创建一个新的HttpClient实例将耗尽 重载下可用的插座数量。这将导致 SocketException错误。
答案 1 :(得分:3)
我想说这是一种标准做法。你也可以使长函数同步
Private Async Function longProcessAsync() As Task(Of Boolean)
Await Task.Delay(10000) ' Simulating web service call
Return True
End Function
在事件处理程序
中等待它Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'some stuff
Dim output As Boolean = Await longProcessAsync()
'continue another stuff when the longProcess completes
End Sub
参考:Async/Await - Best Practices in Asynchronous Programming
始终异步
...“一直异步”意味着你不应该在不仔细考虑后果的情况下混合同步和异步代码。
...
允许异步通过代码库增长是最好的解决方案,但这意味着应用程序有很多初始工作要看到异步代码的真正好处。有一些技术可以将大型代码库逐步转换为异步代码,但它们超出了本文的范围。在某些情况下,使用Task.Wait或Task.Result可以帮助进行部分转换,但您需要了解死锁问题以及错误处理问题。