There is a certain queue, need to go through it with a certain step and create a thread (for each step). The thread, in turn, will run a function that works with COM (need a separate thread, because the Internet writes that COM will not hurt so much).
// Для 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 { }
});
Interesting features occur only with Excel processing. Maybe it's something to do with the COM architecture? https://stackoverflow.com/a/12893711/4143902 (by the way, because of catching this error, I lowered it to 1 thread)
If I run this code on a fast computer with a fast file system, then 1-2 processes appear in the task Manager EXCEL.exe, but if running on a weak VM with a classic disk system, the processes may have about 35 EXCEL.EXE. Question, what am I missing? How do I ask asynchronous loops not to do a new iteration without making sure that the thread inside has ended/died??? p. s. for Word, if specify 4 threads, it keeps 4-5 processes in the Manager.