Problem canceling a process

0

I asked a question previously to cancel the process of compressing files.

I have 2 problems with this code, the program has the function of compressing files in pairs separately getting 2 files in each 7z, the files are bin, cue using 7z, I have a folder full of these files and wanted to compress them

The problems are:

  • When I run the program and click cancel the program but 7z is still working.

  • When the program finishes I realize that it is still compressing the last file, it seems that the program warns that it has completed but it did not wait for the last task to be completed

    public partial class Form1 : Form, IProgress<int>
    {
        private CancellationTokenSource _cancellation;
        public Form1()
        {
            InitializeComponent();
        }
    
        private void ZipFiles(IList<string> files, IProgress<int> progress, CancellationToken token)
        {
            Process x;
    
            Process Zip(string file)
            {
                string game = Path.ChangeExtension(file, null) + ".7z";
                string cue = Path.ChangeExtension(file, ".cue");
                x = new Process()
                {
                    EnableRaisingEvents = true,
                    StartInfo = new ProcessStartInfo
                    {
                        FileName = "7z.exe",
                        Arguments = String.Format("a -t7z \"{0}\" \"{1}\" \"{2}\" -mx=9", game, file, cue),
                        WindowStyle = ProcessWindowStyle.Hidden
                    }
                };
    
                x.Start();
                return x;
            }
    
            var count = 0;
            void Handler(object o, EventArgs a)
            {
                var p = o as Process;
                if (_cancellation.Token.IsCancellationRequested)
                {
                    x.Close();
                    x.Kill();
                    return;
                }
                if (count < files.Count)
                {
                    var next = Zip(files[count]);
                    count++;
                    next.Exited += Handler;
                }
                progress.Report(count * 100 / files.Count);
                p.Exited -= Handler;
            }
            {
                var process = Zip(files[count]);
                process.Exited += Handler;
            }
        }
    
        public void Report(int value)
        {
            Invoke((Action)(() =>
            {
                progressBar.Value = value;
                if (value == 100)
                {
                    btnZip.Enabled = true;
                }
            }));
        }
    
        private void btnZip_Click(object sender, EventArgs e)
        {
            btnZip.Enabled = false;
            _cancellation = new CancellationTokenSource();
            var files = Directory.EnumerateFiles(@"C:\Users\Fabyo.GALUTTI\Desktop\p", "*.bin", SearchOption.AllDirectories)
                .Take(100)
                .ToList();
            ZipFiles(files, this, _cancellation.Token);
        }
    
        private void btnCancel_Click(object sender, EventArgs e)
        {
            _cancellation.Cancel();
            progressBar.Value = 0;
            btnZip.Enabled = true;
        }
    }
    
        
    asked by anonymous 17.05.2018 / 02:10

    1 answer

    1

    You can improve your cancellation process to kill the process. When a process is killed new processes will not be started.

    There may be more elegant ways to solve the problem. In this case I am adding the processes to a list and in the process of cancellation I go through the list to kill the processes.

    The list is returned in object form (it was the stupidest way I found to abstract), and that same object must be passed to the cancel process. If you are not satisfied you can always return the list itself.

    public class Zip
    {
        public object ZipFiles(IList<string> files, IProgress<int> progress)
        {
            Process Zip(string file)
            {
                var process = new Process()
                {
                    EnableRaisingEvents = true,
                    StartInfo = new ProcessStartInfo
                    {
                        FileName = "7z.exe",
                        Arguments = $"a zip.7z {file}",
                        WindowStyle = ProcessWindowStyle.Hidden
                    }
                };
                process.Start();
                return process;
            }
    
            var processes = new ConcurrentBag<Process>();
            var count = 0;
            void Handler(object o, EventArgs a)
            {
                var p = o as Process;
                try
                {
                    if (p.ExitCode != 0)
                    {
                        return;
                    }
                    if (count < files.Count)
                    {
                        var next = Zip(files[count]);
                        processes.Add(next);
                        count++;
                        next.Exited += Handler;
                    }
                    progress.Report(count * 100 / files.Count);
                }
                finally
                {
                    p.Exited -= Handler;
                }
            }
            {
                var process = Zip(files[count]);
                processes.Add(process);
                process.Exited += Handler;
            }
            return processes;
        }
    
        public void Cancel(object token)
        {
            var processes = token as IEnumerable<Process>;
            foreach (var p in processes)
            {
                if (!p.HasExited)
                {
                    p.Kill();
                }
            }
        }
    
    }
    

    Lately you can always have a situation where the file is being used for a short time and the operating system will not let you delete your file. There's absolutely nothing you can do to stop it.

        
    24.05.2018 / 22:26