Problem when cancelling a process

Asked

Viewed 95 times

0

I asked a question earlier 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:

  1. When I run the program and click cancel the program for but 7z continues in memory working.

  2. 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;
    }
}
  • I’ve already solved 99% of the gave problems is your duty to get it working for your specific needs. It clearly demonstrates lack of effort.

  • Bruno I tried and I am trying, I have made several attempts without success, it is not lack of effort, I am a php programmer, I do not know anything of c#, I want to learn but there are things that for me is more difficult, I do not want anyone to do anything for me, I only asked for a help, or an orientation

  • @Brunocosta I’m sorry it seemed like I wasn’t having any effort, but on the contrary, I want to make this program work and learn, I even bought a course at udemy, and I researched a lot, and I tried to use Backgroundworker and it didn’t work, in the tests I did simulating a loop with Sleep works right, cancels normal, but when I run the process with 7z, now it is running straight and ending in seconds or is it not doing what you need to do, I tried to use delegates, Hasexited, but as I said I’m new in c#, but the harder it gets the more I’m enjoying learning

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 probably be more elegant ways to solve the problem. In this case I am adding the processes to a list and in the cancellation process I go through the list to kill the processes.

The list is returned in object form (it was the stupidest form I could find to abstract) and that same object must be passed to the cancellation 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 may 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.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.