Is there something like StopCoroutine but for Tasks?

Hi,

When I use the CancellationTokenSource.Cancel, it stops all the Tasks.
How can I stop a unique Task? (Something like the StopCoroutine Method).

Thanks.

async methods generally should all take a cancellation token as a parameter. Then said method should internally be set up to opt-out when the token is cancelled. There’s various ways to hook into this, and tons of tutorials out there on how to do so as this is regular C# stuff.

So if you have your own async methods, they need to take a token and be set up to end early when the token is raised.

Thanks.

I added a token to the Task like this :
Task.Run(() => MethodAsync(), cts.Token);
I’ll search on Google to see how to add a token to the async methods.

I guess it’s possible to reuse an async method that was canceled.
When I cancel a Task, it’s not possible to reuse it.

Like I said, your async method itself should take a cancellation token, and back out if the token is raised. Somewhere in this link there’s this code roughly:

public static async Task LongRunningTask(CancellationToken token)
{
    for (int i = 0; i < count; i++)
    {
        // some task
       
        if (token.IsCancellationRequested)
        {
            // return or throw error
        }
    }
}

There’s a lot more to it than that, of course. Lots of reading ahead of you. Took me a while to get my head around it.

Am I correct that this is analogous to just passing a delegate into a coroutine to test if quit?

IEnumerator MyCoRo( System.Func<bool> ShouldQuit)
{
  while( true)
  {
    if (ShouldQuit()) yield break;

    yield return null;
  }
}

Roughly analagous I suppose? Cancellation tokens are a bit more lightweight, but also managed. You need to dispose the sources once you’re done with them, but you can also combine multiple tokens into a single source, as a good way to ‘bubble up’ cancellations.

I mostly use async code because, A: My code looks a lot cleaner, not having to StartCoroutine everything, B: they can be independant of game objects, and C: it makes it easier to interface with operations like System.IO.ReadAllTextAsync, etc.

But you do end up with a bit more boilerplate if you go down the route of cancellation tokens. I’m still wrapping my head around how to best use them, to be honest.

Is it possible to pause a task instead of canceling it?
I’m able to launch a Task several times but when I cancel it, I can’t launch it again.
This is a little code I attach to an empty game object to test cancel and see the result in the console:

using UnityEngine;
using System.Threading.Tasks;
using System.Threading;

public class TaskCancellation : MonoBehaviour
{
    private readonly CancellationTokenSource cTokenSource = new();
 
    private void Update()
    {
        // Input Manager
        if(Input.anyKeyDown)
        {
            // Run Task (Space)
            if(Input.GetKeyDown(KeyCode.Space))
            {
                Task.Run(() => MethodAsync(cTokenSource.Token), cTokenSource.Token);
            }

            // Cancel Task (LeftShift)
            if(Input.GetKeyDown(KeyCode.LeftShift))
            {
                cTokenSource.Cancel();
            }
        }
    }

    // Asynchronous Method
    private async Task MethodAsync(CancellationToken token)
    {
        // Iteration
        for(int i = 1; i <= 10; i++)
        {
            // Write on the console every second (10 times)
            await Task.Delay(1_000);
            Debug.Log("<color=yellow>MethodAsync Iteration : </color>" + i + "\n");

            // Cancel Task if requested
            if(token.IsCancellationRequested)
            {
                Debug.Log("<color=red>MethodAsynd canceled</color>\n");
                return;
            }
        }

        // Console : Task finished
        Debug.Log("<color=red>MethodAsynd finished</color>\n");
    }
}

Tasks nor co-routines aren’t designed to stop and start again. That’s not their purpose.

What is your actual end goal here?

Just doing some tests and learning.
Thanks.
I like coroutines but since everybody in the tutorials say that async methods are better than coroutines, I started to learn async await Task.

I created a bool as a switch and with if else, I can make the Task stop and start :

        private void SwitchTaskOnOff()
        {
            // if Task isn't running : Create a CancellationTokenSource and Run Task
            if(isTaskRunning == false)
            {
                cTokenSource = new CancellationTokenSource();
                Task.Run(() => MethodAsync(cTokenSource.Token), cTokenSource.Token);
            }
            // if Task is running : Cancel Task
            else if(isTaskRunning == true)
            {
                cTokenSource.Cancel();
            }

            // Switch Task On/Off
            isTaskRunning = !isTaskRunning;
        }

I don’t think any is better. They have their pros and cons, and their time and place

I would watch this if you haven’t already:

https://www.youtube.com/watch?v=7eKi6NKri6I

And if you do want to pursue more async, I would recommend UniTask: https://github.com/Cysharp/UniTask

Main differences in short:

Coroutines:

  • Automatically aborted when the MonoBehaviour is destroyed or set inactive
  • Easy to stop at will
  • Simpler to use in general

Tasks:

  • Can be run on background threads
  • Can return a value
  • Does not require a MonoBehaviour instance

My advise is to just keep on using coroutines as long as it feels intuitive.
Then if you need to return a value or perform work in parallel consider using Tasks instead.