【发布时间】:2020-11-21 09:20:32
【问题描述】:
有一定的队列,需要通过一定的步骤,并创建一个线程(每一步)。反过来,该线程将运行一个与 COM 一起工作的函数(需要一个单独的线程,因为 Internet 上写着 COM 不会受到太大伤害)。
// Для Excel асинхронность очень вредна, т.к. можно поймать COM исключения 0x800A03EC, 0x800AC472 и подобные
// т.к. Excel использует главный поток и при закрытии COM дочерние потоки могут потерять COM интерфейсы
parallelOpt.MaxDegreeOfParallelism = 1;
// Для COM нужен отдельный, личный поток, поэтому многопоточность делаем так
Parallel.ForEach(listsFileInfoExcel, parallelOpt, (listsBlock) =>
{
try
{
Thread t = new Thread(OfficeClass.ExcelProcessing);
// Данным id будем связывать текущий поток и COM процесс
string idThread = Guid.NewGuid().ToString();
lock (objWorkThreadExcelLock)
{
dictThreadExcel.Add(idThread, 0);
}
try
{
t.IsBackground = false;
t.Start(new Dictionary<string, object> {
{"listBlock",listsBlock},
{"pathHeaderImage",ImageHeaderExcel},
{"pathBackgroundImage",ImageBackgroundExcel},
{"Action",actionForDocument},
{"idThread",idThread}
});
// Скорее всего внешний COM процесс завис
if (!t.Join(180000))
{
throw new Exception($"Принудительно завершён поток с файлами {String.Join(", ", listsBlock.Select(obj => obj.FullName).ToArray())}");
}
}
catch (Exception ex)
{
AddLog(TypeLog.Error, ex.Message);
t.Abort();
lock (objWorkThreadExcelLock)
{
if (dictThreadExcel[idThread] != 0)
{
Killing(dictThreadExcel[idThread]);
}
}
}
finally
{
lock (objWorkThreadExcelLock)
{
dictThreadExcel.Remove(idThread);
}
}
}
catch { }
});
只有在 Excel 处理中才会出现有趣的功能。也许这与 COM 架构有关? https://stackoverflow.com/a/12893711/4143902(顺便说一下,因为发现这个错误,我把它降低到1个线程)
如果我在具有快速文件系统的快速计算机上运行此代码,则任务管理器 EXCEL.exe 中会出现 1-2 个进程,但如果在具有经典磁盘系统的弱 VM 上运行,这些进程可能有大约35 EXCEL.EXE。问题,我错过了什么?我如何要求异步循环不要进行新的迭代而不确保里面的线程已经结束/死亡??? 页。 s。对于 Word,如果指定 4 个线程,则在 Manager 中保留 4-5 个进程。
【问题讨论】:
-
你到底在做什么?你是在阻塞线程池中的线程,为每个人创建另一个线程,为每个人做一些废话,然后加入就可以了?使用
object值创建字典,因为.. 什么,结构过于结构化? -
Parallel.ForEach的原因是什么?您没有在循环内执行任何 CPU 密集型工作。您只是在启动一个线程,然后等待它完成。另外,如果代码中的 cmets 对于理解问题至关重要,您能否将它们翻译成英文? -
COM 需要 STAThread 模型(Thread 提供),我使用 Parallel.ForEach 是因为它方便排队。不,cmets 并不是特别有用。问题更多的是为什么 (1 thread Parallel.ForEach) -> (1 thread Thread ?!) -> (1 COM interface ???) 在工作过程中,10分钟后在后台等待几十个EXCEL.EXE来自 COM 接口的进程 ...
-
Excel 不需要
STAThread环境,但需要单线程来创建和交互。并尝试asynchronously。不要用Thread包装代码,它根本没用。您可以运行一些 Excel,例如最多 4 个实例并使用它打开/关闭工作簿队列。将生产者/消费者编程模式视为一种实现方法。 -
感谢您的建议,但此链接的想法略有不同 - 打开了 1 个文档并且异步处理了表格。就我而言,只需要 1 个文件、1 个处理程序,并将其设为并行队列。使用额外的内部线程是因为在处理数千个文件时会发生不可预知的情况,并且线程可以无限期地运行。我决定,如果超过 3 分钟,就说明出了问题,你需要关闭紧急状态,即使有工作。
标签: c# multithreading com