【发布时间】:2024-05-22 07:00:01
【问题描述】:
我有一个应用程序,它通过执行 ICR 识别并根据坐标切割 tiff 文件的某些字段来处理 tiff 图像,然后将每个图像块保存到数据库中。我们每分钟需要处理很多图像,所以我们需要有多个线程同时处理图像。
应用程序运行的环境是 Windows Server 2012 DataCenter 版本,具有 256GB 的 RAM、2 个 Intel Xeon 处理器(每个 18 核)和 7 个 RAID 0 配置的 SSD 驱动器或类似的东西。
因此,我们预计最多可以并行运行 28 个线程。为此,我们使用 TPL 库来启动并行任务。这是一个代码示例:
private void btnIniciar_Click(object sender, EventArgs e) {
if (managerTokensCancelacion != null)
managerTokensCancelacion.Dispose();
managerTokensCancelacion = new CancellationTokenSource();
tokenCancelacion = managerTokensCancelacion.Token;
for (int cnt = 0; cnt < 28; cnt++) {
Task.Factory.StartNew(myAction(cnt+1), tokenCancelacion);
}
}
private Action myAction(int numThread) {
return () => {
try {
while (true) {
(new BusinessClass()).splitAndReadImage(numThread));
tokenCancelacion.ThrowIfCancellationRequested();
}
}
catch (OperationCanceledException ex) {
Console.WriteLine("Cancelled process");
}
};
}
我们有一个业务类来处理所有的逻辑,但基本功能是在数据库中搜索图像(我们有我们的并发机制来避免不同的线程处理同一个图像)。我们处置所有对象以避免内存泄漏。
问题是,应用程序在最初的一两分钟内运行良好,具体取决于我启动了多少进程。如图所示,它使用了所有核心(这不是生产服务器,但它有 8 个核心)。
但是,当我处理近 400 张图像时,它会变慢,并且任务可能仅使用一个内核按顺序运行。
我的代码有什么地方做错了吗?正如我之前提到的,我们没有内存泄漏问题,它使用相同的内存运行并且不会持续增加,我们在每次迭代中处理所有对象,但突然变慢并停止使用所有可用内核。也许是关于 Windows Server 的?还是 TPL 库的错误?数据库查询在每次迭代时运行良好。
【问题讨论】:
-
你的
splitAndReadImage在做什么?从数据库中读取? -
是的。接下来是流程: 1. 从数据库中获取图像 2. 当它找到它时,我有一个先前加载到我的应用程序中的坐标数组 3. 我遍历这个数组切割每一块 4. 我将每一块保存在数据库 5. 最后,我更新了一个我得到完整图像的字段,表明我已经处理它没有问题。
-
我怀疑你的代码是同步的,不允许其他线程访问相同的资源?所以只使用一个线程,因此只有一个核心。为了阻止我们猜测并给出答案,您需要发布
splitAndReadImage的相关代码。如果它涉及数据库,则最好使用异步数据库调用。 -
我们需要看到你流程中的主要核心逻辑。
-
我已经调试了很多代码,查询并没有变慢,查询时间几乎一直都一样。
标签: c# .net task-parallel-library windows-server-2012