class procedure Join(const task1, task2: TProc); overload; class procedure Join(const task1, task2: TOmniTaskDelegate); overload; class procedure Join(const tasks: array of TProc); overload; class procedure Join(const tasks: array of TOmniTaskDelegate); overload;Later it got an optional parameter of the IOmnITaskConfig type, but that didn’t change its simplicity. You called Join, it executed some code in parallel, and only when all code blocks completed its execution, your main thread would proceed by executing the statement following the Join call.
Then I started to think about handling exceptions (just as I did for the Parallel.Future) and somehow this simplicity didn’t feel right to me anymore. At the same time I got involved in a prolonged discussion with Антон Алисов (Anton Alisov) and together we defined new features that new Join would have to have.