大佬教程收集整理的这篇文章主要介绍了.Net Core 3.1 异步控制台应用程序在 VS 之外运行时挂起,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
目标:针对 S3 URI 列表中的每个项目,获取对象数量。
我的 .Net Core 3.1 控制台应用程序在从 VS 2019 运行时运行良好,但一旦列表大小超过 5000 项左右,从 cmd(或任务计划程序、.bat 文件等)运行时就会出现问题。
在剩下大约 500-1000 个任务之前,一切似乎都很好。然后,大约 75% 的时间,剩余的任务似乎永远不会完成,应用程序永远挂起......尽管 RAM 使用量在任务管理器中减少到几乎为零。
我对 Async 还很陌生,我已经尝试根据我看到的无数解决方案重构一堆,但似乎无法弄清楚。
注意事项:
namespace Mynamespace
{
public class MyClass
{
private static Datatable dt;
private static IAmazonS3 clIEntS3;
static async Task Main(String[] args)
{
dt = <Call DB,get S3 URIs>;
clIEntS3 = new AmazonS3ClIEnt();
IEnumerable<Task<int>> callAPITasksquery = from row in dt.AsEnumerable() SELEct GetS3DataAsync(row);
List<Task<int>> APITasks = callAPITasksquery.ToList();
int @R_283_10586@l = 0;
while (APITasks.Any())
{
// if (APITasks.Count % 100 == 0) await Console.out.WritelineAsync($"{APITasks.Count} remaining.");
Task<int> finishedTask = await Task.WhenAny(APITasks);
APITasks.Remove(finishedTask);
@R_283_10586@l += await finishedTask;
}
}
static async Task<int> GetS3DataAsync(DaTarow row)
{
var response = await clIEntS3.ListObjectsV2Async(new ListObjectsV2request { Bucketname = row[0],Prefix = row[1] });
// Console.Writeline(response.S3Objects.Count().ToString());
return 1;
}
}
}
我看到的唯一问题是在这段代码中,它在 O(n^2) 时间内运行:
@H_772_26@int @R_283_10586@l = 0;
while (apiTasks.Any())
{
// if (apiTasks.Count % 100 == 0) await Console.out.WriteLineAsync($"{apiTasks.Count} remaining.");
Task<int> finishedTask = await Task.WhenAny(apiTasks);
apiTasks.Remove(finishedTask);
@R_283_10586@l += await finishedTask;
}
如果不需要输出,则将其替换为单个 Task.WhenAll
:
var @R_283_10586@ls = await Task.WhenAll(apiTasks);
var @R_283_10586@l = @R_283_10586@ls.sum();
如果您确实需要输出,那么您可以通过补全一次重新排序,然后await
每一个。有 some blogs on how to do that,或者您可以使用 Nito.AsyncEx
:
int @R_283_10586@l = 0;
var orderedApiTasks = apiTasks.OrderByCompletion();
for (int i = 0; i != orderedApiTasks.Count; ++i)
{
@R_283_10586@l += await orderedApiTasks[i];
if (i % 100 == 0) await Console.out.WriteLineAsync($"{orderedApiTasks.Count - i} remaining.");
}
,
以下批处理解决方案有效。它在 2-3 秒内恢复每个批次(如果在调试器中运行约 10 秒)
感谢 https://www.michalbialecki.com/2018/04/19/how-to-send-many-requests-in-parallel-in-asp-net-core/ 并感谢所有人的帮助!
@H_772_26@using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Data;
using Amazon.S3;
using System.Linq;
using Amazon.S3.Model;
namespace MyNamespace
{
public class S3PrefixGrabber
{
private static IAmazonS3 clientS3;
static async Task Main(String[] args)
{
var query = "SELECT bucket,prefix from myTable";
DataTable dt = GetstuffFromDB(query);
List<S3Prefix> unpopulatedList = (from DataRow dr in dt.Rows SELEct new S3Prefix() { B = dr[0].ToString(),P = dr[1].ToString() }).ToList();
var batchSize = 1000;
int numberOfBatches = (int)R_358_11845@ath.Ceiling((doublE)unpopulatedList.Count() / batchSizE);
List<S3Prefix> populatedList = new List<S3Prefix>();
for (int i = 0; i < @R_674_10793@erOfBatches; i++)
{
var currentItems = unpopulatedList.Skip(i * batchSizE).Take(batchSizE);
var tasks = currentItems.SELEct(id => GetS3DataAsync(id));
populatedList.AddRange(await Task.WhenAll(tasks));
}
}
static async Task<S3Prefix> GetS3DataAsync(S3Prefix s3Item)
{
clientS3 = new AmazonS3Client();
var response = await clientS3.ListObjectsV2Async(new ListObjectsV2request { BucketName = s3Item.b,Prefix = s3Item.P });
s3Item.O = response.S3Objects.Count;
return s3Item;
}
}
public class S3Prefix
{
public String B { get; set; }
public String P { get; set; }
public int O { get; set; }
}
}
运行 10k 条记录,RAM 为 75MB,CPU 为 40%
运行 300k 条记录,RAM 为 700MB,CPU 为 40%
日志中的一个片段(我没有包含在上面的代码中),仅供参考:
06:32:52.310: ================== 开始 ==================
06:32:52.795:查询:SELECT 存储桶,前缀 FROM myTable
06:32:52.874:打开连接
06:32:54.205:灌装适配器
06:33:06.309: 313863 行从 DB
返回
06:33:07.647:批处理...批处理大小:1000 批处理:314
06:33:07.647:开始第 1/314 批……在 02.84 秒内完成。
06:33:10.492:开始第 2/314 批次......在 02.48 秒内完成。
06:33:12.977:开始第 3/314 批次......在 02.19 秒内完成。
...
06:38:55.435:开始批次 150/314... 02.32 秒内完成。
06:38:57.761:开始批次 151/314... 02.17 秒内完成。
06:38:59.936:开始批次 152/314... 02.27 秒内完成。
...
06:45:13.579:开始批次 312/314... 02.17 秒内完成。
06:45:15.751:开始批次 313/314... 02.35 秒内完成。
06:45:18.105:开始批次 314/314... 02.10s 完成。
06:45:20.211:将 313863 行写入 CSV...完成。
06:45:23.086:DB 行:313863 CSV 行:313863 NoTinS3:0 InS3ButNotFound:0
06:45:23.087:在 12:30.77 秒内完成。
06:45:23.092:==================结束==================
以上是大佬教程为你收集整理的.Net Core 3.1 异步控制台应用程序在 VS 之外运行时挂起全部内容,希望文章能够帮你解决.Net Core 3.1 异步控制台应用程序在 VS 之外运行时挂起所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。