Многопоточность не означает что любому потоку разрешено соваться в любое место.

У меня на работе в программе глобальное пространство объектов поделено на объектные подпространства. Взаимодействие между ними осуществляется через очереди сообщений (точнее - указателей на сообщения). Вызов процедуры для манипулирования объектами из чужого потока карается возбуждением исключения в потоке-нарушителе.

> Например, DevCommanders.par или Views.Deposit - такого рода "буферы" для взаимодействия компонентов.

В них надо расставить ASSERTы на исполнимость только, например, из главного потока ББ.

Пусть процедура Threading.GetCurrentThreadId() возвращает целое число - номер потока из которого она вызвана (все потоки перенумерованы). Если манипулирование какими-то данными допускается только из потока с номером t1, тогда в начало соответствующих процедур вставьте такой код:## Код:
```
PROCEDURE Procedure ();
BEGIN
  ASSERT(Threading.GetCurrentThreadId() = t1);
  ...
```
Аналог этой проверки на C#:## Код:
```
if (System.Threading.Thread.CurrentThread.ManagedThreadId != this.threadId)
{
  throw new System.InvalidOperationException("threadsafe violation");
}
```
Код "if (System.Threading.Thread.CurrentThread.ManagedThreadId != this.threadId)" выполняется тактов за пять. То есть практически бесплатно можно осуществлять (динамический) контроль потокобезопасности в объектных подпространствах.