Combining a lot of the ideas above, here's what I would try.
Job creators register the fact that they have jobs available and the labor necessary. These postings are separated by type:
1. Health / Animal Care
2. Construction
3. Designations
4. Building Jobs (Seed Planting, Harvest, Workshop tasks, Lever, etc)
5. Hauling
6. Hunting / Fishing / Trapping
Similarly, Idle dwarves register their availability and the labors they have turned on. If at any point there are no Idle dwarves, stop processing.
Each category of jobs is processed in ascending order. If there are jobs and available dwarves of appropriate labors, then the details of each job is determined and a job priority assigned.
First, jobs select materials. Materials selected should be the closest available of the appropriate type.
Next, jobs select from the available dwarves. This selection should be made based on the total distance to be traveled modified by walking speed, the appropriateness of the dwarf (strong dwarves for hauling, highly skilled dwarves for workshop tasks, etc), and the dwarf's preferences (RUBIES? I LOVE Rubies! - thanks, CharonX).
Distance, both for materials and dwarves, should be based on actual path. To reduce the cost of this calculation, perhaps the available entities should be sorted by straight-line distance. Then, in ascending order calculate the actual paths until the shortest known path is less than the next object's straight-line distance.
Finally, the jobs which have selected materials and a dwarf are sorted by job length minus a factor of the amount of time the job has waited. The lowest number is chosen and the job is started.
Each job always selects the best of the available dwarves and materials. If another job is successfully assigned one of the selected items, the job which was unsuccessful is marked for recalculation. However, that recalculation only occurs if there are available dwarves and there are no jobs waiting ahead of it in the list. If its best choice wasn't good enough, don't even worry about 2nd best.
Stockpiles, Farming Plots, and other objects which might create multiple job requests only register a single job available. If that job is selected, a second job request is created with a new waiting time. If there are still available dwarves, this second request may jump to the head of the list and be started immediately.
Also, the time a job has waited should be stockpile neutral. Otherwise, you'll end up with stockpiles which get more greedy as they age.
As an extension, the selection of materials might include materials currently tasked with a non-destructive job. If a plump helmet is just being returned to the stockpile, the brewer might take off after that plant. If he catches the dwarf hauling it, he'll take it from him and go back to the brewery. If he doesn't, he'll still have started walking towards the stockpile earlier than he would have before.
I would stop the majority of job canceling. If a job does not have the available materials, it should just be highlighted in the job list and elsewhere.