【发布时间】:2017-12-31 02:23:53
【问题描述】:
我有一个控制台应用程序,它查询数据库,然后在循环中将一些记录发布到 REST API(该 api 不支持批量发布,因此我必须遍历每条记录并单独发布,如果相关)。数据库访问速度很快,没有问题,根据我设置的计时器,api post 循环也是如此,但是应用程序本身在工作完成后需要很长时间才能退出。
这在我介绍Parallel.Foreach 以加快发布速度后开始发生。在使用非并行循环之前,发布 1000 条记录平均需要大约 10 分钟,但应用程序会在完成后立即返回并退出(如预期的那样)。在并行循环到位后,根据我使用的Stopwatch 计时器,这将减少到平均约 44 秒,但是应用程序直到大约 2 分钟后才会退出 - 在所有工作完成后约 1 分 15 秒完成。
该应用没有做任何“额外”的事情。它进入main,main 调用一个方法从数据库中检索一些记录(1-2 秒),将这些记录中的 1000 条转发到另一个方法,该方法循环遍历它们并将每个记录发布到 api,然后退出。除了,由于某种原因,在这种情况下它不会立即退出。
我在调用发布方法之前在main 中放置了一个stopwatch 计时器,并在方法返回后立即记录时间,并且计时器与方法内部的计时器对齐,平均约46 秒。所以延迟发生在发布方法返回之后但在main 函数退出之前,但此时没有定义任何事情要做。调试没有显示任何异常。这是一个与并行循环产生的所有“徘徊”的对象相关的取消分配问题吗?
无论我是在附加调试器的情况下运行还是在为发布而构建时直接执行二进制文件,都会发生这种情况(因此不是分离延迟问题)。我看过其他类似这样的 SO 问题,但他们的方法没有产生任何影响。任何意见将不胜感激。
发帖功能代码:
public ProcessingState PostClockingRecordBatchParallel(List<ClockingEvent> batch, int tokenExpiryTolerance)
{
log.Info($"Attempting to post batch of {batch.Count.ToString()} clocking records to API with an auth token expiry tolerance of {tokenExpiryTolerance} seconds");
try
{
ProcessingState state = new ProcessingState() { PendingRecords = batch };
List<ClockingEvent> successfulRecords = new List<ClockingEvent>();
Stopwatch timer = new Stopwatch();
ServicePointManager.UseNagleAlgorithm = false; //Performance optimization related to RestSharp lib
authToken = Authenticate();
timer.Start();
Parallel.ForEach(state.PendingRecords, pr =>
{
successfulRecords.Add(PostClockingRecord(pr, tokenExpiryTolerance));
});
//Prior non-parallel version
//state.PendingRecords.ForEach(pr =>
//{
// successfulRecords.Add(PostClockingRecord(pr, tokenExpiryTolerance));
//});
state.PendingRecords = state.PendingRecords.Except(successfulRecords).ToList();
state.LastSuccessfulRecord = successfulRecords.OrderBy(r => r.EventID).Last().EventID;
log.Info($"PostClockingRecordBatchParallel - Time elapsed: {new TimeSpan(timer.ElapsedTicks).ToString()}");
return state;
}
catch (Exception ex)
{
log.Fatal($"Failed to post records to API (exception encountered: {ex}).");
throw;
}
}
【问题讨论】:
标签: c# rest console-application restsharp