Попробуйте BackgroundWorker . Поддерживаются обновления хода выполнения и отмена запущенной задачи.
Если вы хотите, чтобы один поток ожидал, пока другой поток завершит свою работу, то Monitor.Wait и Monitor.Pulse хороши, как и ManualResetEvent. Тем не менее, они на самом деле бесполезны для отмены запущенной задачи.
Если вы хотите написать свой собственный код отмены, вы можете просто где-то иметь поле, к которому имеют доступ оба потока. Отметьте это как изменчивое, например:
private volatile bool cancelling;
Сделайте так, чтобы основной поток установил для него значение true, и чтобы рабочий поток периодически проверял его и устанавливал для него значение false, когда он закончил.
Это на самом деле не сравнимо с наличием «глобальной переменной», поскольку вы все еще можете ограничить область действия переменной семафора, чтобы она была закрытой для класса.