gpt4 book ai didi

c# - 在完成时响应异步 sql 调用

转载 作者:行者123 更新时间:2023-11-30 22:31:26 24 4
gpt4 key购买 nike

背景:

我有一项服务可以批量查询数据库的历史结果。批处理基于开始时间和结束时间。所有批处理之间的数据是互斥的,因此对于一组给定的批处理,它们可以按任何顺序运行。一些批处理可能比其他批处理需要更多的时间来执行。如果任何批处理失败,则整个过程将中止/停止并记录错误。向客户端返回数据时,需要合并所有批处理的数据。

问题:

尽快将数据返回给客户端。

初步解决方案:

最初我按顺序同步执行批处理。这并没有利用数据相互排斥的事实。初次使用后,发现这种加载方式耗时过长。经过一些调试,我发现缓慢的主要原因是sql查询的执行时间。因此,下一个解决方案是尝试使用 BeginExecuteReader()EndExecuteReader() 异步执行每个批处理。在异步调用所有批处理后,服务将在 while 循环中等待并每 300 毫秒轮询一次以检查是否有任何查询已完成。如果是,那么它将被读取。

int batchCount = 0, resultCount = 0;
List<AsyncDataResult> asyncCalls = new List<AsyncDataResult>();

while (true)
{
if (asyncCalls.Count == 0)
{
break;
}

if ((asyncCalls[resultCount]).AsyncResult.IsCompleted)
{
ReadAsyncResultsFromDb(asyncCalls[resultCount]);
asyncCalls.RemoveAt(resultCount);
}

resultCount++;
if (resultCount >= asyncCalls.Count)
{
resultCount = 0;
Thread.Sleep(300);
}
}

上述方法减少了大型数据集的加载时间,但对于非常小的数据集(但跨越许多批处理),轮询实际上增加了加载延迟。

问题:

  1. 如何异步执行 sql,但不进行轮询?
  2. 每批完成后立即开始阅读?

更新:对此感到抱歉,但我忘记在调用异步调用的同一方法中添加需要返回的部分。这样做的原因是我需要填充的数据集作为参数传递给此方法。从初学者开始使用 IAsyncCallback 需要我更改整个类。我希望我不必那样做。

最佳答案

为什么要主动投票?您生成的每个异步操作都会返回一个具有 WaitHandle 的 IAsyncResult。使用 WaitAny() 并让系统通知您:

/// <summary>
/// Do something useful with a completed query
/// </summary>
/// <param name="result"></param>
/// <returns>
/// true if the query failed;
/// false if the query was successful
/// </returns>
private static bool DoSomethingUseful( IAsyncResult result )
{
throw new NotImplementedException() ;
}

static void Main( string[] args )
{
List<IAsyncResult> batch = SpawnBatch() ;
bool errorOccurred = ProcessCompletedBatches( batch , DoSomethingUseful) ;

if ( errorOccurred )
{
CancelPending( batch ) ;
}

return ;

}

public static bool ProcessCompletedBatches( List<IAsyncResult> pending , Func<IAsyncResult,bool> resultHandler )
{
bool errorOccurred = false ;

while ( ! errorOccurred && pending.Count > 0 )
{
WaitHandle[] inFlight = pending.Select( x => x.AsyncWaitHandle ).ToArray() ;

int offset = WaitHandle.WaitAny( inFlight ) ;

IAsyncResult result = pending[offset] ;
pending.RemoveAt(offset) ;

errorOccurred = resultHandler(result) ;

}

return errorOccurred ;

}

关于c# - 在完成时响应异步 sql 调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9234730/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com