我想提供一个围绕网络I / O功能的异步包装器。目前我看到两种方式只有很小的区别。
第一
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
第二
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
我应该更喜欢第一种方式(正确键入,使用匿名函数)还是第二种方式(在对象中装箱,没有编译器创建的辅助函数)?它是否有所作为,如果是,为什么?或者是否有更好的方法为阻塞呼叫提供*异步功能?
编辑:Additionaly GetMacAddressFromArp已重载。它需要IPAddress或String(主机名)。如果有一种方法可以保存样板代码,那就更好了。
编辑以澄清:我收到了n个IP地址列表。我需要为每个人调用一个函数。此函数对windows API(SendARP
)进行阻塞(网络)调用,每次调用约0.1到2秒。我想以异步和并行方式调用它们,所以我不想要一个伪异步包装器,而是一个事实上让我调用异步的包装器。
然后我想以一种方式调用我的包装函数(对于每个元素),这种方式会产生(聚合的)返回值的列表,或者甚至更好地以每次调用返回时引发事件的方式。
我想使用最低的.Net Framework版本,这使我能够做到这一点。 4.0可以,但我不能使用4.5。
答案 0 :(得分:4)
我建议你不要这样做。 Stephen Toub has an excellent explanation why this is a bad idea.
即使你忽略了大师的建议,还有其他一些问题:
Task
构造函数和Task.Start
。这不适合await
兼容的任务;你应该使用Task.Run
代替。我有blog post和MSDN 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