This page shows how to follow and control the VAL 3 tasks of a Staubli CS8 or CS9 controller: list them with their state, their program line and their runtime error, then suspend, resume or kill a task.

## List the tasks

`GetTasks()` returns every task of the controller.

**C# : TaskList**
```csharp
using UnderAutomation.Staubli;
using UnderAutomation.Staubli.Soap.Data;

public class TaskList
{
    static void Main()
    {
        var controller = new StaubliController();
        controller.Connect("192.168.0.254");

        /**/
        ControllerTask[] tasks = controller.Soap.GetTasks();

        foreach (ControllerTask task in tasks)
        {
            // State: Idle, Transition, Running, Stepping, Stopped
            Console.WriteLine($"{task.Name} ({task.State}), priority {task.Priority}, created by {task.CreatedBy}");

            // Line of the VAL 3 program that the task executes
            ProgramLine line = task.ProgramLine;
            if (line != null)
                Console.WriteLine($"  {line.ProgramName}:{line.LineNumber} {line.LineContent}");

            // Runtime error of the task, 0 when there is none
            if (task.RuntimeError != 0)
                Console.WriteLine($"  Error {task.RuntimeError}: {task.RuntimeErrorDescription}");
        }
        /**/

        controller.Disconnect();
    }
}
```

**Python : TaskList**
```python
from underautomation.staubli.staubli_controller import StaubliController

controller = StaubliController()
controller.connect("192.168.0.254")

##
tasks = controller.soap.get_tasks()

for task in tasks:
    # state: Idle, Transition, Running, Stepping, Stopped
    print(f"{task.name} ({task.state.name}), priority {task.priority}, created by {task.created_by}")

    # Line of the VAL 3 program that the task executes
    line = task.program_line
    if line is not None:
        print(f"  {line.program_name}:{line.line_number} {line.line_content}")

    # Runtime error of the task, 0 when there is none
    if task.runtime_error != 0:
        print(f"  Error {task.runtime_error}: {task.runtime_error_description}")
##

controller.disconnect()
```

**Matlab : TaskList**
```matlab
NET.addAssembly(fullfile(pwd, 'net48', 'UnderAutomation.Staubli.dll'));
import UnderAutomation.Staubli.*

controller = StaubliController();
controller.Connect('192.168.0.254');

%%
tasks = controller.Soap.GetTasks();

for i = 1:tasks.Length
    task = tasks(i);

    % char() gives the name of an enumeration value: Idle, Running, Stopped...
    fprintf('%s (%s), created by %s\n', char(task.Name), char(task.State), char(task.CreatedBy));

    % Runtime error of the task, 0 when there is none
    if task.RuntimeError ~= 0
        fprintf('  Error %d: %s\n', task.RuntimeError, char(task.RuntimeErrorDescription));
    end
end
%%

controller.Disconnect();
```

| Property                  | Meaning                                                        |
| ------------------------- | -------------------------------------------------------------- |
| `Name`                    | Name of the task                                               |
| `CreatedBy`               | The project that created the task                              |
| `State`                   | `Idle`, `Transition`, `Running`, `Stepping` or `Stopped`       |
| `Priority`                | Priority of the task                                           |
| `ProgramLine`             | Application, program, line number and text of the current line |
| `RuntimeError`            | Code of the runtime error of the task, `0` when there is none  |
| `RuntimeErrorDescription` | Text of the runtime error                                      |

`RuntimeError` is the way to detect that a VAL 3 program stopped on an error. See [Monitor the state of the robot](/staubli/documentation/how-to-monitor-state).

## Suspend, resume and kill

A task is identified by its name and by the project that created it: pass `Name` and `CreatedBy` as they come from `GetTasks()`.

**C# : TaskControl**
```csharp
using UnderAutomation.Staubli;
using UnderAutomation.Staubli.Soap.Data;

public class TaskControl
{
    static void Main()
    {
        var controller = new StaubliController();
        controller.Connect("192.168.0.254");

        /**/
        // A task is identified by its name and by the project that created it
        ControllerTask task = controller.Soap.GetTasks().First(t => t.Name == "myTask");

        // Pause the task
        controller.Soap.TaskSuspend(task.Name, task.CreatedBy);

        // Continue it
        controller.Soap.TaskResume(task.Name, task.CreatedBy);

        // Stop it for good
        controller.Soap.TaskKill(task.Name, task.CreatedBy);
        /**/

        controller.Disconnect();
    }
}
```

**Python : TaskControl**
```python
from underautomation.staubli.staubli_controller import StaubliController

controller = StaubliController()
controller.connect("192.168.0.254")

##
# A task is identified by its name and by the project that created it
task = next(t for t in controller.soap.get_tasks() if t.name == "myTask")

# Pause the task
controller.soap.task_suspend(task.name, task.created_by)

# Continue it
controller.soap.task_resume(task.name, task.created_by)

# Stop it for good
controller.soap.task_kill(task.name, task.created_by)
##

controller.disconnect()
```

- `TaskSuspend` pauses the task.
- `TaskResume` continues a suspended task.
- `TaskKill` stops the task for good.

When the task does not exist, the method throws a `CustomSoapException` with the code `TaskNotFound`.

## Try it in the demo application



## Reference

**Methods of SoapClientBase**
```csharp
// Get all the tasks available on the controller
ControllerTask[] GetTasks();

// Kill a task on the controller
void TaskKill(string taskName, string createdBy);

// Resume a task on the controller
void TaskResume(string taskName, string createdBy);

// Suspend a task on the controller
void TaskSuspend(string taskName, string createdBy);
```

Every method also exists in an asynchronous version, with the same name followed by `Async` and an optional `CancellationToken`.

**Members of Soap.Data.ControllerTask**
```csharp
public class ControllerTask {
    // Initializes a new instance of the <xref href="UnderAutomation.Staubli.Soap.Data.ControllerTask" data-throw-if-not-resolved="false"></xref> class.
    public ControllerTask()

    // Name of the entity that created the task.
    public string CreatedBy { get; set; }

    public override bool Equals(object obj)

    public override int GetHashCode()

    // Name of the task.
    public string Name { get; set; }

    // Priority level of the task.
    public int Priority { get; set; }

    // Current program line being executed by the task.
    public ProgramLine ProgramLine { get; set; }

    // Runtime error code (0 if no error).
    public int RuntimeError { get; set; }

    // Human-readable description of the runtime error.
    public string RuntimeErrorDescription { get; set; }

    // Current execution state of the task.
    public ControllerTaskState State { get; set; }

    public override string ToString()
}
```

**Members of Soap.Data.ControllerTaskState**
```csharp
public enum ControllerTaskState {
    // Task is idle and not executing.
    Idle = 0

    // Task is currently running.
    Running = 2

    // Task is executing step by step.
    Stepping = 3

    // Task is stopped.
    Stopped = 4

    // Task is transitioning between states.
    Transition = 1
}
```

**Members of Soap.Data.ProgramLine**
```csharp
public class ProgramLine {
    // Initializes a new instance of the <xref href="UnderAutomation.Staubli.Soap.Data.ProgramLine" data-throw-if-not-resolved="false"></xref> class.
    public ProgramLine()

    // Name of the application containing the program.
    public string ApplicationName { get; set; }

    public override bool Equals(object obj)

    public override int GetHashCode()

    // Content of the line being executed.
    public string LineContent { get; set; }

    // Line number currently being executed.
    public int LineNumber { get; set; }

    // Name of the program.
    public string ProgramName { get; set; }

    public override string ToString()
}
```