Si las llamadas a SP1 seguidas por SP2 son atómicas, deben combinarse en T-SQL. O perder la transacción c#. Estás prolongando la transacción innecesariamente con viajes de ida y vuelta.
Además, ¿por qué tiene UPDLOCK en SP1UPDLOCK pero no para SP1? No puedo ver por qué. Si el problema son las sugerencias de bloqueo, no las use. Si algo es serializable (¿por qué?), de nuevo, conviértalo en una sola llamada atómica
Tenga en cuenta que el valor predeterminado es LECTURA COMPROMETIDA de todos modos
Finalmente, ¿quieres decir que "semáforo" no está bloqueado? Usando sp_getapplock controlará el flujo a través del código sin usar bloqueos en los datos