首先,我在这里搜索并看到了许多类似的问题,但我所想要的都不是。
我有一个需要一些时间才能返回值的函数
为简化起见,假设它是:
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
最佳答案
根据评论,您的“长期运行”功能会发送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错误。