Для оптимального решения вам все равно придется проанализировать свой код и найти все места, чтобы проверить, хочет ли пользователь отменить длительную операцию. Это верно как для простой процедуры, так и для многопоточного решения - вы хотите, чтобы действие завершалось через несколько десятых секунды, чтобы ваша программа выглядела отзывчивой для пользователя.
Теперь, что я хотел бы сделать в первую очередь, это создать интерфейс (или абстрактный базовый класс) с такими методами, как:
IModelTransformationGUIAdapter = interface
function isCanceled: boolean;
procedure setProgress(AStep: integer; AProgress, AProgressMax: integer);
procedure getUserInput1(...);
....
end;
и измените процедуру, чтобы иметь параметр этого интерфейса или класса:
procedure MyTransformation(AGuiAdapter: IModelTransformationGUIAdapter);
Теперь вы готовы реализовать вещи в фоновом потоке или непосредственно в основном потоке графического интерфейса, сам код преобразования не нужно будет менять, как только вы добавите код для обновления хода выполнения и проверки запроса на отмену. Вы реализуете интерфейс только по-разному.
Я бы определенно остался без рабочего потока, особенно если вы все равно хотите отключить графический интерфейс. Чтобы использовать несколько процессорных ядер, вы всегда можете найти части процесса преобразования, которые относительно разделены, и обработать их в своих собственных рабочих потоках. Это даст вам гораздо лучшую пропускную способность, чем отдельный рабочий поток, и это легко сделать с помощью AsyncCalls . Просто запустите столько параллельно, сколько у вас процессорных ядер.
Edit:
IMO этот ответ Роба Кеннеди является самым проницательным из всех, поскольку он не фокусируется на деталях реализации, а на лучшем опыте для пользователя. Это то, для чего ваша программа должна быть оптимизирована.
Если на самом деле нет способа либо получить всю информацию до начала преобразования, либо запустить ее и исправить некоторые вещи позже, тогда у вас все еще есть возможность заставить компьютер выполнять больше работы, чтобы у пользователя был лучший опыт. Из ваших различных комментариев я вижу, что в процессе преобразования есть много точек, в которых выполнение ветвится в зависимости от пользовательского ввода. Один из примеров, который приходит на ум, - это точка, в которой пользователю приходится выбирать между двумя альтернативами (например, горизонтальным или вертикальным направлением) - вы можете просто использовать AsyncCalls для запуска обоих преобразований, и есть вероятность, что в тот момент, когда пользователь выбрал свою альтернативу, оба результаты уже рассчитаны, так что вы можете просто представить следующий диалог ввода. Это лучше использовать многоядерные машины. Может быть, идея продолжить.