猿问

如何进行多个异步调用并从找到匹配记录的第一次调用返回数据然后停止剩余的异步调用

我需要通过遍历连接字符串来进行多个数据库调用。数据库中只有 1 条匹配记录,如果我找到匹配记录,那么我可以返回数据并取消其他异步调用。


using (var Contexts = instContextfactory.GetContextList())

{

    foreach(var context in Contexts.GetContextList())

    {    

        // how do I make all the calls and return data from the first call that finds data and continue with further process.(don't care about other calls if any single call finds data.           

        context.Insurance.GetInsuranceByANI(ani);

    }

}

通过 ANI 获取保险


public Task<IEnumerable<Insurance>> GetInsuranceByANI(string ani)

{

    using (ITransaction transaction = Session.Value.BeginTransaction())

    {

        transaction.Rollback();

        IDbCommand command = new SqlCommand();

        command.Connection = Session.Value.Connection;


        transaction.Enlist(command);


        string storedProcName = "spGetInsurance";


        command.CommandText = storedProcName;

        command.Parameters.Add(new SqlParameter("@ANI", SqlDbType.Char, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Default, ani));


        var rdr = command.ExecuteReader();

        return Task.FromResult(MapInsurance(rdr));

    }

}

例如:我正在循环使用 5(a, b, c, d, e) 个不同的数据库连接字符串。我需要对所有 5 个数据库进行异步调用。如果我在 db : b 中找到匹配的记录,那么我可以返回该数据并继续下一步,并且可以停止调用其他数据库


翻翻过去那场雪
浏览 131回答 2
2回答

慕尼黑的夜晚无繁华

获取值后立即返回该值如何。不允许流程向前移动并打破循环。using (var Contexts = instContextfactory.GetContextList())&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;foreach(var context in Contexts.GetContextList())&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// how do I make all the calls and return data from the first call that finds data and continue with the further process.(don't care about other calls if any single call finds data.&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var result = await context.Insurance.GetInsuranceByANI(ani);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(result.Any())&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return result.First();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}&nbsp; &nbsp; }

子衿沉夜

为了简单起见,您应该首先改回您的GetInsuranceByANI方法以再次同步。稍后我们将生成任务以异步调用它。public IEnumerable<Insurance> GetInsuranceByANI(string ani){&nbsp; &nbsp; using (ITransaction transaction = Session.Value.BeginTransaction())&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; transaction.Rollback();&nbsp; &nbsp; &nbsp; &nbsp; IDbCommand command = new SqlCommand();&nbsp; &nbsp; &nbsp; &nbsp; command.Connection = Session.Value.Connection;&nbsp; &nbsp; &nbsp; &nbsp; transaction.Enlist(command);&nbsp; &nbsp; &nbsp; &nbsp; string storedProcName = "spGetInsurance";&nbsp; &nbsp; &nbsp; &nbsp; command.CommandText = storedProcName;&nbsp; &nbsp; &nbsp; &nbsp; command.Parameters.Add(new SqlParameter("@ANI", SqlDbType.Char, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Default, ani));&nbsp; &nbsp; &nbsp; &nbsp; var rdr = command.ExecuteReader();&nbsp; &nbsp; &nbsp; &nbsp; return MapInsurance(rdr);&nbsp; &nbsp; }}现在来实现异步搜索所有数据库的方法。我们将为每个数据库创建一个任务,在线程池线程中运行。这是值得商榷的,但我们正在努力让事情变得简单。我们还实例化 a CancellationTokenSource,并将其传递Token给所有Task.Run方法。这只会确保在我们得到结果后,不会再启动更多任务。如果线程池中的可用线程多于要搜索的数据库,则所有任务将立即开始,取消令牌实际上不会取消任何内容。换句话说,无论如何,所有启动的查询都将完成。这显然是一种资源浪费,但我们再次努力让事情变得简单。启动任务后,我们将进入一个等待下一个任务完成的循环(使用方法Task.WhenAny)。如果找到结果,我们取消令牌并返回结果。如果未找到结果,我们将继续循环以获得下一个结果。如果所有任务都完成但我们仍然没有结果,我们将返回 null。async Task<IEnumerable<Insurance>> SearchAllByANI(string ani){&nbsp; &nbsp; var tasks = new HashSet<Task<IEnumerable<Insurance>>>();&nbsp; &nbsp; var cts = new CancellationTokenSource();&nbsp; &nbsp; using (var Contexts = instContextfactory.GetContextList())&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; foreach (var context in Contexts.GetContextList())&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tasks.Add(Task.Run(() =>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return context.Insurance.GetInsuranceByANI(ani);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }, cts.Token));&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; while (tasks.Count > 0)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; var task = await Task.WhenAny(tasks);&nbsp; &nbsp; &nbsp; &nbsp; var result = await task;&nbsp; &nbsp; &nbsp; &nbsp; if (result != null && result.Any())&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cts.Cancel();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return result;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; tasks.Remove(task);&nbsp; &nbsp; }&nbsp; &nbsp; return null;}使用示例:IEnumerable<Insurance> result = await SearchAllByANI("12345");if (result == null){&nbsp; &nbsp; // Nothing fould}else{&nbsp; &nbsp; // Do something with result}
随时随地看视频慕课网APP
我要回答