Vb.net 这是异步工作的良好实践吗?

Vb.net 这是异步工作的良好实践吗?,vb.net,Vb.net,首先,我在这里搜索了很多类似的问题,但没有一个是我想要的 我有一个函数,它需要一些时间来返回一个值 为了简化,我们假设: Private Function longProcess() As Boolean Threading.Thread.Sleep(10000) Return True End Function 我想运行它并得到它的值,比如说点击按钮1 我尝试了下面的代码,它工作得很好 Private Async Sub Button1_Click(sender As Obj

首先,我在这里搜索了很多类似的问题,但没有一个是我想要的

我有一个函数,它需要一些时间来返回一个值 为了简化,我们假设:

Private Function longProcess() As Boolean
    Threading.Thread.Sleep(10000)
    Return True
End Function
我想运行它并得到它的值,比如说点击按钮1

我尝试了下面的代码,它工作得很好

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()


根据您的“长时间运行”函数发送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
的方法更好,因为当您从另一个线程发送请求时,该线程什么也不做,只是等待响应。其中,通过使用
HttpClient
(或其他类)的异步
async wait
方法,整个工作将在一个线程上完成,而不会阻塞应用程序的主UI线程

关于
HttpClient
的注意事项:即使在
Using
块中使用的
HttpClient
的上述示例中,在应用程序生命周期中也应该只使用一个实例

从Microsoft文档:

HttpClient打算实例化一次并在整个过程中重复使用 应用程序的生命周期。特别是在服务器应用程序中, 为每个请求创建一个新的HttpClient实例将耗尽 重载下可用的插座数量。这将导致 SocketException错误


我认为这是一种标准做法。也可以使长函数异步

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
参考:

始终异步

…“一路异步”意味着您不应该在没有仔细考虑后果的情况下混合使用同步和异步代码

允许异步通过代码库增长是最好的解决方案,但这意味着应用程序需要进行大量的初始工作才能从异步代码中看到真正的好处。有几种将大型代码库增量转换为异步代码的技术,但它们不在本文的讨论范围之内。在某些情况下,使用Task.Wait或Task.Result可以帮助进行部分转换,但您需要注意死锁问题以及错误处理问题


当你使用第一个选项时,你有问题吗?如果你不继续使用它,直到你面对一些问题。不面对代码问题并不意味着它是好的。我想问的是,它在技术上是否好,或者是否有一种更好的短方法来做到这一点。您希望的是“短”于一行代码。使用第一个选项,您可以在另一个线程上执行函数,该线程在UI客户端事件处理程序中正确等待。所以,如果第一个选项没有违反您的要求,您可以继续使用它。如果长时间运行的函数使用一些外部资源(fily系统、数据库、web服务等),那么第一个选项不是最佳做法,因为使用
async wait
可以更有效地访问外部资源,而无需使用额外的线程在我的例子中,longProcess()函数正在发送HttpWebRequest。感谢您的回答。我使用的是HttpWebRequest,不是HttpClient。我真的不知道如何编辑您的代码示例以使用HttpWebRequest。如果你能编辑它,我将不胜感激。我也希望你能告诉我为什么这种方式比我的好,以及“完全”异步是什么意思。@Youssef13,你会发现这个答案很有用,提供了更多关于HttpClient的链接-感谢回复:)我可以用HttpWebRequest来做,有GetResponseAsync()方法,但我仍然想知道为什么这比使用Task.Run要好,因为使用
Task.Run
您将使用另一个线程,而使用
…Async
方法,所有工作都将在一个线程中完成。使用
Task.Run
您将保留一个线程,该线程将不执行任何操作-只等待响应。这是
async wait
特性的主要优点,读取不是无限的,因此它们也可以被视为系统资源。
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