调用参数化任务的哪种方式更好?

时间:2013-10-03 22:09:57

标签: .net vb.net task-parallel-library async-await

我想提供一个围绕网络I / O功能的异步包装器。目前我看到两种方式只有很小的区别。

  1. 第一

    Public Shared Async Function GetMacAddressFromArpAsync(ipAddress As IPAddress) As Threading.Tasks.Task(Of String)
        Dim t As New Threading.Tasks.Task(Of String)(Function() GetMacAddressFromArp(ipAddress))
        t.Start()
        Await t
        Return t.Result
    End Function
    
  2. 第二

    Public Shared Async Function GetMacAddressFromArpAsync(ipAddress As IPAddress) As Threading.Tasks.Task(Of String)
        Dim t As New Threading.Tasks.Task(Of String)(Function(ip As IPAddress) GetMacAddressFromArp(ip), ipAddress)
        t.Start()
        Await t
        Return t.Result
    End Function
    
  3. 我应该更喜欢第一种方式(正确键入,使用匿名函数)还是第二种方式(在对象中装箱,没有编译器创建的辅助函数)?它是否有所作为,如果是,为什么?或者是否有更好的方法为阻塞呼叫提供*异步功能?

    编辑:Additionaly GetMacAddressFromArp已重载。它需要IPAddress或String(主机名)。如果有一种方法可以保存样板代码,那就更好了。

    编辑以澄清:我收到了n个IP地址列表。我需要为每个人调用一个函数。此函数对windows API(SendARP)进行阻塞(网络)调用,每次调用约0.1到2秒。我想以异步和并行方式调用它们,所以我不想要一个异步包装器,而是一个事实上让我调用异步的包装器。

    然后我想以一种方式调用我的包装函数(对于每个元素),这种方式会产生(聚合的)返回值的列表,或者甚至更好地以每次调用返回时引发事件的方式。

    我想使用最低的.Net Framework版本,这使我能够做到这一点。 4.0可以,但我不能使用4.5。

1 个答案:

答案 0 :(得分:4)

我建议你不要这样做。 Stephen Toub has an excellent explanation why this is a bad idea.

即使你忽略了大师的建议,还有其他一些问题:

  • 您正在使用Task构造函数和Task.Start。这不适合await兼容的任务;你应该使用Task.Run代替。我有blog postMSDN article,其中包含该指导。
  • await执行任务,然后返回Result。这是不必要的,因为await将返回结果本身。
  • 删除所有仪式后,返回任务比使用Async方法返回Await的结果更有效率。

所以,如果你想提供一个假的异步包装器(我推荐),那么你可以这样做:

Public Shared Function GetMacAddressFromArpAsync(ipAddress As IPAddress) As Task(Of String)
    Return Task.Run(Function() GetMacAddressFromArp(ipAddress))
End Function