If BLAS threading cannot be controlled and persists with multithreading, consider using explicit parallel processing to ensure proper thread control. For example:
library(parallel)
cl <- makeCluster(1) # Single core
clusterExport(cl, list("explained_variance_aov", "data"))
results <- parLapply(cl, paste0("PC", 1:3000), function(pc) { explained_variance_aov(pc, data, "covar") })
stopCluster(cl)
results <- do.call(rbind, results)