Main возвращает неверное значение

255
28 февраля 2017, 14:31

Есть программа, которая по выполнению должна вернуть 0 или 1 в случае успеха/отказа. Операции можно прервать сочетанием клавиш. При прерывании в глобальную переменную stopState должно падать значение true, но оно остаётся false, соответственно Main отвечает неверно. Помогите разобраться

Вот код:

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;
                        }
                    }
                }
            }
        }
    }
}

Сверился с ответом: Если добавить listenKey(Join), то программа не завершится, пока этот самый джойн не произойдёт, но он не обязательно должен происходить.

При срабатывании Ctrl+c stopState всё-равно считает false, добавил в listenKey при срабатывании stopState = true; однако в итоге программа возвращает всё тот же 0;

Обновил код на актуальный

Answer 1

Наверное, вы хотели использовать оператор == но получилось присваивание:

(stopState = false)

Так же, вы запускаете поток listenKeyThread.Start() и не дожидаетесь его остановки, а уже проверяете жив ли он или нет (он жив и крутит цикл). Если нужно дождаться выполнения потока, то вызовите следующей строкой listenKeyThread.Join() тогда всё заработает так, как вы ожидаете.

Конечно же, хочется ещё отметить, что для решения вашей задачи вам совершенно ненужен поток listenKeyThread. Что сейчас происходит? Запускается поток listenKeyThread и в тоже время основной поток Main ждет завершения этого потока и ничего полезного не делает. В вашем случае, логично было бы перенести код этого потока в Main, а listenKeyThread забыть как страшный сон.

READ ALSO
Извлечение файлов из архива

Извлечение файлов из архива

Здравствуйте! Есть класс который извлекает файлы из архива с перезаписью:

290
Удалить файлы, загруженные в WebBrowser

Удалить файлы, загруженные в WebBrowser

Есть 3 формыКаждая по очереди открывается, происходят определенные операции (скачивание изображений, затем их конвертация и вставка в поля...

242
Не работает SetResolution на Bitmap

Не работает SetResolution на Bitmap

Немного не понимаю, почему не работает данный код:

250
Запуск программ

Запуск программ

Здравствуйте! Возможно ли сделать так что-бы операционная система не требовала установкиNET Framework и других компонентов для запуска программы...

243