Поскольку вы используете C библиотеку из C# с помощью C++/CLI слоя, это звучит как ваша ссылка отношение выглядеть следующим образом:
(C# приложение) - динамический -> (C++/CLI DLL) - -static -> (библиотека C)
фон:
Потому что вы заявили, что у вас нет никакого способа изменить или иначе фиксируя вашу библиотеку C, вы на самом деле нет никакого способа решения проблемы безопасности потоков без дублирования библиотеки C в памяти так или иначе, что позволит эффективно дублировать глобальные данные, которые/безусловно, вызывают конфликты потоков.
Независимо от того, как вы на это смотрите, ваш единственный способ решить это путем дублирования DLL (ваш текущий подход) потребует от вас знать, сколько дубликатов вам нужно заблаговременно, и каждая из этих DLL будет немного отличаться экспортированные имена символов (например, каждому классу или пространству имен для каждого класса класса, управляемого C++/CLI, потребуется другое имя класса). Как вы заявили, это действительно грубо (и я добавлю трудно управлять и невозможно масштабировать).
Решение:
Я думаю, что ваш лучше и чище вариант с помощью дублирования EXE. Для этого вы вставляете новый EXE перед своей DLL C++/CLI и динамически связываете его с помощью механизма IPC по вашему выбору (IPC Mechanisms in C# - Usage and Best Practices). Позволяет называть этот EXE вашим сервисом EXE. Если вы создаете экземпляр службы EXE для каждого потока в основном приложении C#, то каждая служба EXE будет загружать свою собственную копию библиотеки C++/CLI DLL и, следовательно, собственную версию библиотеки C. Это означает, что каждый поток работает с копией библиотеки C через службу EXE.
Вот что ваша ссылка отношение будет выглядеть следующим образом:
(C# application)--IPC-->(C# service EXE)--dynamic-->(C++/CLI DLL)--static-->(C library)
В натуральном выражении файла, он будет выглядеть следующим образом:
MainApp.exe--IPC-->ServiceApp.exe--dynamic-->CppCliWrapper.dll
Для оптимизации этого решения, вы должны стараться избегать тяжелыми создание/удаление потоков, поскольку это связано с созданием/удалением службы EXE. Например, вы можете предварительно выделить потоки X при запуске и использовать эти потоки в течение всего жизненного цикла приложения. Вы также можете подумать о том, чтобы выполнить операции над оптимизацией расходов на IPC. Все это зависит от потребностей и деталей вашего приложения.
Чтобы это сделать еще больше, вы можете потенциально масштабировать это решение на всех компьютерах, если вы выберете механизм IPC, который работает через TCP/IP. Затем вы можете обрабатывать свои операции на столько машин, сколько хотите. Именно так многие компании превращают библиотеки DLL в горизонтально масштабируемые сервисы. Это не так просто, как кажется, но еда для вас, если вам нужно масштабировать эту штуку.
'Я прибегал к копированию (с небольшими вариациями) всего несколько раз. Как именно это помогает? Если вы изменяете имена глобальных/статических переменных, чтобы не возникало конфликтов, вы также можете обозначить их как протектора. Если вы не меняете имена, каковы эти незначительные вариации? –
имена библиотек, поэтому они загружаются как «разные» вещи –
Статические библиотеки не загружаются, они связаны. Имена библиотек не влияют на процесс связывания статических библиотек. DLL в Windows может вести себя, как вы описываете, но не статические библиотеки. –