1

我想为网络 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
    

我应该更喜欢第一种方式(正确键入,使用匿名函数)还是第二种方式(装箱在一个对象中,编译器没有创建辅助函数)?它有什么不同吗?如果有,为什么?或者有没有更好的方法来为我的阻塞调用提供一个 *Async 函数?

编辑:另外 GetMacAddressFromArp 被重载。它需要一个 IPAddress 或一个字符串(主机名)。如果有一种方法可以保存样板代码,那就更好了。

编辑澄清:我得到了 n 个 IPAddresses 的列表。我需要为每一个调用一个函数。此函数对 Windows API ( SendARP) 进行阻塞(网络)调用,每个调用大约需要 0.1 到 2 秒。我想异步和并行地调用它们,所以我不想要一个的异步包装器,而是一个实际上使我的调用异步的包装器。

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

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

4

1 回答 1

4

我建议你根本不要这样做。Stephen Toub 有一个很好的解释,为什么这是一个坏主意。

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

  • 您正在使用Task构造函数和Task.Start. 这不适合await-compatible 任务;你应该Task.Run改用。我有一篇包含该指南的文和MSDN 文章。
  • 您正在await执行任务,然后返回Result. 这是不必要的,因为await将返回结果本身。
  • 一旦你删除了所有的仪式,只返回任务比创建一个Async方法来返回一个Await.

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

Public Shared Function GetMacAddressFromArpAsync(ipAddress As IPAddress) As Task(Of String)
    Return Task.Run(Function() GetMacAddressFromArp(ipAddress))
End Function
于 2013-10-03T23:51:45.843 回答