【问题标题】:Multiple Async Functions, First to return the correct result多个异步函数,首先返回正确的结果
【发布时间】:2020-08-28 13:58:29
【问题描述】:

我在网上找不到我想要的东西,也找不到正确的条款。就是这样。

我有一些异步函数:

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.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

我想在不需要等待所有异步函数完成的情况下执行以下操作。它们可以被终止,只要第一个完成的满足返回标准 - First Non-Nothing 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

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

解决方案

基于 Richard Zhang 和 this 的解决方案

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

虽然并不完美,但性能确实得到了显着提升。

【问题讨论】:

标签: .net vb.net uwp


【解决方案1】:

我们可以使用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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多