多个异步函数,首先返回正确的结果



>我在网上找不到我想要的东西,也找不到正确的术语。所以它来了。

我有一些异步函数:

Public Async Function Func1(Arg as T) As Task(Of Reply) 
Public Async Function Func2(Arg as T) As Task(Of Reply)
Public Async Function Func3(Arg as T) As Task(Of Reply)
.
.

它们都接受相同的参数并返回相同类型的"Reply"。 在函数中,Reply.Info 分配有效对象或 Nothing。

Public Class Reply
Public Property Info As Object = Nothing
Public ReadOnly Property Available As Boolean
Get
Return Info IsNot Nothing
End Get
End Property
End Class

我想执行以下操作,而无需等待所有异步函数完成。它们可以终止,以便只要第一个完成符合返回标准 - 第一个非无 Reply.Info。

Public Async Function RunFunc(Arg as T) as Task(Of Reply)
Dim Reply1 As Reply = Await Func2(Arg)
Dim Reply2 As Reply = Await Func3(Arg)
Dim Reply3 As Reply = Await Func4(Arg)
'Return the first one where Reply.Available = True
End Function

如果有人能对此提供一些见解,那就太好了。

溶液

基于张理查德的解决方案和这个

Dim TaskList As New List(Of Task(Of Reply)) From {
Func1(Search),
Func2(Search),
Func3(Search)
}
Dim CompletedTask As Task(Of Reply)
Do
CompletedTask = Await Task.WhenAny(TaskList.ToArray)
TaskList.Remove(CompletedTask)
Loop While CompletedTask.IsFaulted AndAlso TaskList.Count > 0
TaskList.Clear()
If Not CompletedTask.IsFaulted Then
Dim CompletedReply As Reply = Await CompletedTask
If CompletedReply.Available AndAlso CompletedReply.SomeOtherProperty Then
Return Reply
Else
Return 'Handles non-expected but non-error return
End If
Else
Return 'Handles all error situations
End If

虽然不完美,但性能确实显着提高。

我们可以使用Task.WhenAny来满足我们的需求

Private Async Sub InitTask(Of T)(ByVal Arg As T)
Dim tasks = New List(Of Task(Of Reply))()
tasks.Add(Func1(Arg))
tasks.Add(Func2(Arg))
tasks.Add(Func3(Arg))
Dim completeTask = Await Task.WhenAny(tasks.ToArray())
Dim result = Await completeTask
End Sub

考虑到你的实际返回值可能是空的,你可以在相关函数中判断它是否为空并抛出异常。任务将过滤掉引发异常的任务,并仅获取最终结果。

Private Async Function Func1(Of T)(ByVal Arg As T) As Task(Of Reply)
' get reply
If reply.Available Then
Return reply
Else
Throw New ArgumentException("not invalid data")
End If
End Function

最新更新