There is a program that, upon execution, should return 0 or 1 in case of success / failure. Operations can be interrupted by a shortcut key. When interrupted, the value of true should fall into the global variable stopState, but it remains false, respectively, Main does not respond correctly. Help me to understand
Here is the code:
Program.cs:
using System; using System.IO; using System.Threading; namespace ConsoleThreadTest { class Program { // основной поток static void MainThread(string typeJob,string fileInput, string fileOut) { Zip zip = new Zip(); zip.Action(typeJob, fileInput, fileOut); } // фоновый поток static void listenKey(Thread th) { ConsoleKeyInfo cki; Console.TreatControlCAsInput = true; while (true) { cki = Console.ReadKey(); if ((cki.Modifiers & ConsoleModifiers.Control) != 0 && cki.Key == ConsoleKey.C) { stopState = true; Console.WriteLine("StopState = {0}", stopState); Console.WriteLine("Программа остановлена вручную"); Console.WriteLine("Целевой файл удалён"); th.Abort(); break; } } } private static void ActionJob(string typeJob, string fileInput, string fileOut) { if (FileCheck.CheckPath(fileInput, fileOut)) { if (FileCheck.FileExistCheck(fileInput, fileOut)) { Thread actionThread = new Thread(() => MainThread(typeJob, fileInput, fileOut)); Thread listenKeyThread = new Thread(() => listenKey(actionThread)); listenKeyThread.IsBackground = true; actionThread.Start(); listenKeyThread.Start(); } } } public static bool stopState = false; static int Main(string[] args) { //stopState = false; if (args.Length == 3) { ActionJob(args[0], args[1], args[2]); } else { Console.WriteLine("Парметры запуска заданы неверно"); } if ((!File.Exists(args[2]) && (stopState == false))) { return 0; } else return 1; } } } FileCheck.cs:
using System; using System.IO; using System.Text.RegularExpressions; namespace ConsoleThreadTest { class FileCheck { public static bool CheckPath(string fileInput, string fileOut) { // паттерн для проверки второго и третьего параметров string pattern = @"([a-zA-Z]:(\/|\\))((\w+(\/|\\))*(\w+(.\w+)?))"; if (Regex.IsMatch(fileInput, pattern)) { if (Regex.IsMatch(fileOut, pattern)) { return (true); } else { Console.WriteLine("третий параметр не является путём к файлу"); Console.ReadLine(); return false; } } else { Console.WriteLine("второй параметр не является путём к файлу"); Console.ReadLine(); return false; } } public static bool FileExistCheck(string fileInput, string fileOut) { if (File.Exists(fileInput)) { if (!File.Exists(fileOut)) { return true; } else { Console.WriteLine("Имя целевого файла уже используется"); return false; } } else { Console.WriteLine("Указанного файла не существует"); return false; } } } } Zip.cs:
using System; using System.IO; using System.IO.Compression; using System.Threading; namespace ConsoleThreadTest { class Zip { public void Action(string typeJob, string fileInput, string fileOut) { Console.WriteLine("Ctrl + c - для отмены..."); if (FileCheck.FileExistCheck(fileInput,fileOut)) { using (FileStream sourceStream = new FileStream(fileInput, FileMode.Open)) { using (FileStream targetStream = File.Create(fileOut)) { switch (typeJob) { case "compress": Console.WriteLine("Упаковка файла: {0} в архив {1}", fileInput, fileOut); using (GZipStream compressionStream = new GZipStream(targetStream, CompressionMode.Compress)) { try { sourceStream.CopyTo(compressionStream); break; } catch (ThreadAbortException) { if (sourceStream != null && compressionStream != null && targetStream != null) { sourceStream.Close(); compressionStream.Close(); targetStream.Close(); } File.Delete(fileOut); break; } } case "decompress": Console.WriteLine("Распаковка архива: {0} в файл {1}", fileInput, fileOut); using (System.IO.Compression.GZipStream decompressionStream = new GZipStream(sourceStream, CompressionMode.Decompress)) { try { decompressionStream.CopyTo(targetStream); break; } catch (ThreadAbortException) { if (sourceStream != null && decompressionStream != null && targetStream != null) { sourceStream.Close(); decompressionStream.Close(); targetStream.Close(); } File.Delete(fileOut); break; } catch (InvalidDataException) { Console.WriteLine("Возможно путь к архиву указывает на файл иного типа"); File.Delete(fileOut); break; } } default: Console.WriteLine("Первый аргумент указан неверно"); Console.WriteLine("Следует выбрать compress или decompress"); File.Delete(fileOut); break; } } } } } } } I checked the answer: If you add listenKey (Join), the program will not end until this same join happens, but it does not have to happen.
When Ctrl + c is triggered, stopState still considers false, added to listenKey when triggered stopState = true; however, in the end, the program returns the same 0;
Updated the code to the current
(smth) && (false)will always be false - Grundy.Join()? Find the line withlistenKeyThread.Start();and then below (after.Start()) addlistenKeyThread.Join();- Artyom Okonechnikov