Search code examples
c#taskmultitaskingcancellation-token

Stop a long nested loop task


I need to stop a task from running when the user hits the escape key. The problem is the task is running a method like:

void Start(){

    while(long loop){
        while(!userEvent) System.Windows.Forms.Application.DoEvents();
        for(another long loop){
             while(more loops)
        }
    }
}

And all I've learned browsing the forums on this topic is that to use CancellationToken you need to handle it like this:

if (token.IsCancellationRequested)
{
        // Clean up here, then...
        "cleanup".Dump();
        token.ThrowIfCancellationRequested();
}

Since there are so many loops, checking if the cancellation is requested would be highly inefficient and ugly to read.

The task needs to stop when the window the events inside are being read off of so I can't just check the CancellationToken before the next iteration, it would need to be pretty much everywhere

So, is there a way to stop the task whatever loop it's in? It doesn't need to be with CancellationTokens but it seems to be the "standard" way of doing this.

Also, the method Start() wasn't used as a Task at first but that would make it so that even after closing the window the main thread kept running the code unless I used a bunch of if (windowClosed) break which were equally impractical.


Solution

  • Exception just propagates through no matter how many loops you are in.

    private void Form1_KeyDown(object sender, KeyEventArgs e)
    {
        switch (e.KeyCode)
        {
            case Keys.Escape:
                cancallation.Cancel();
                break;
        }
    }
    
    private CancellationTokenSource cancallation = new CancellationTokenSource();
    
    private void button1_Click(object sender, EventArgs e)
    {
        Task.Run(() =>
        {
            while (...)
            {
                for (...)
                {
                    cancallation.Token.ThrowIfCancellationRequested();
                }
            }
        }, cancallation.Token);
    }
    
    private void Form1_FormClosed(object sender, FormClosedEventArgs e)
    {
        if (cancallation.IsCancellationRequested == false)
        {
            cancallation.Cancel();
        }
    }