首先,我在这里搜索并看到了许多类似的问题,但我所想要的都不是。

我有一个需要一些时间才能返回值的函数
为简化起见,假设它是:

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错误。

09-30 18:14
查看更多