I am doing a simple console application that loads files from a database into a hashset. These files are then processed in a parallel foreach loop. This console application does launch a new Process object for each file it needs to process. So it opens new console windows with the application running. I am doing it this way because of logging issues I have if I run parsing from within the application where logs from different threads write into each other.
The issue is, when I do close the application, the parallel foreach loop still tries to process more files before exiting. I want all tasks in the code to stop immediately when I kill the application. Here is code excerpts:
My cancel is borrowed from: Capture console exit C#
Essentially the program performs some cleanup duties when it receives a cancel command such as CTRL+C or closing window with X button
The code I am trying to cancel is here:
class Program
{
private static bool _isFileLoadingDone;
static ConcurrentDictionary<int, Tuple<Tdx2KlarfParserProcInfo, string>> _currentProcessesConcurrentDict = new ConcurrentDictionary<int, Tuple<Tdx2KlarfParserProcInfo, string>>();
static void Main(string[] args)
{
try
{
if (args.Length == 0)
{
// Some boilerplate to react to close window event, CTRL-C, kill, etc
LaunchFolderMode();
}
}
}
}
Which calls:
private static void LaunchFolderMode()
{
//Some function launched from Task
ParseFilesUntilEmpty();
}
And this calls:
private static void ParseFilesUntilEmpty()
{
while (!_isFileLoadingDone)
{
ParseFiles();
}
ParseFiles();
}
Which calls:
private static void ParseFiles()
{
filesToProcess = new HashSet<string>(){@"file1", "file2", "file3", "file4"} //I actuall get files from a db. this just for example
//_fileStack = new ConcurrentStack<string>(filesToProcess);
int parallelCount = 2
Parallel.ForEach(filesToProcess, new ParallelOptions { MaxDegreeOfParallelism = parallelCount },
tdxFile =>{
ConfigureAndStartProcess(tdxFile);
});
}
Which finally calls:
public static void ConfigureAndStartProcess(object fileName)
{
string fileFullPath = fileName.ToString();
Process proc = new Process();
string fileFullPathArg1 = fileFullPath;
string appName = @".\TDXXMLParser.exe";
if (fileFullPathArg1.Contains(".gz"))
{
StartExe(appName, proc, fileFullPathArg1); //I set up the arguments and launch the exes. And add the processes to _currentProcessesConcurrentDict
proc.WaitForExit();
_currentProcessesConcurrentDict.TryRemove(proc.Id, out Tuple<Tdx2KlarfParserProcInfo, string> procFileTypePair);
proc.Dispose();
}
}
The concurrent dictionary to monitor processes uses the following class in the tuple:
public class Tdx2KlarfParserProcInfo
{
public int ProcId { get; set; }
public List<long> MemoryAtIntervalList { get; set; } = new List<long>();
}
For the sake of how long these code excerpts are, I omitted the 'StartExe()' function. All it does is set up arguments and starts the Process object process.
Why is the parallel.Foreach insisting on running even after I close the program? Is there a better parallel processing method I can use which will allow me to kill whatever files I am currently processing immedietly without trying to start a new process. Which the parallel.Foreach does?
I have tried killing it with Parallel State Stop method but it still tries to process more files before finally exiting.