A task is a piece of code that can be executed.
A task can have multiple attributes (or arguments, if you prefer). The value of an attribute might contain references to a property. These references will be resolved before the task is executed.
Tasks have a common structure:
<name attribute1="value1" attribute2="value2" ... />
where name is the name of the task, attributeN is the attribute name, and valueN is the value for this attribute.
There is a set of built-in tasks, along with a number of optional tasks, but it is also very easy to write your own.
All tasks share a task name attribute. The value of this attribute will be used in the logging messages generated by Ant.
Tasks can be assigned an id attribute:
<taskname id="taskID" ... />
where taskname is the name of the task, and taskID is a unique identifier for this task. You can refer to the corresponding task object in scripts or other tasks via this name. For example, in scripts you could do:
<script ... >
to set the foo attribute of this particular task instance. In another task (written in Java), you can access the instance via project.getReference("task1").
Note 1: If "task1" has not been run yet, then it has not been configured (i.e., no attributes have been set), and if it is going to be configured later, anything you've done to the instance may be overwritten.
Note 2: Future versions of Ant will most likely not be backward-compatible with this behaviour, since there will likely be no task instances at all, only proxies.