Detached Threads
С этого места по подробнее. Сдается мне, вы несколько не понимаете модели потоков Windows.
Кратко.
Единица исполнения кода в Windows - поток (thread). Тогда как процесс (process) - единица заявки на ресурсы ОС (хэндлы на файлы, объекты синхронизации, сокеты и прочее). При запуске процесса автоматически создается один поток исполнения (в котором выполняется функция int main(char* argv[], int argc)), ОС завершает процесс после выхода из main, если же были другие потоки, то они также будут автоматически завершены.
Обычно, поток в Windows исполняется до тех пор, пока не произойдет выход из функции этого потока, но в принципе его можно насильно завершить специальными АПИ (TerminateThread).
Дождаться завершения потока можно стандартной функцией WaitForSingleObject, передав ей хэндл на поток. Для более сложной синхронизации потоков нужно пользоваться примитивами типа семафора, мутекса, ивента, думаю с их семантикой вы знакомы.
В .NET поведение программы аналогично, разве что есть удобная объектно-ориентированная обертка (классы Thread, Semaphore и др.).
А вообще в .NET есть домены приложений (AppDomains) предназначенные для программной изоляции кода. Домен приложения сродни процессу в ОС, но исполняется в рамках самого процесса. По-умолчанию при запуске .NET процесса создается Default-домен приложения, но никто не мешает создать дочерние домены (например для изолированного исполнения недоверенного кода).