我有一个使用 ASP WebApi 的服务。每个 http 请求都会转换为一个线程,该线程需要执行一些数据操作(可能更改数据)。 API层是用C#写的,数据操作是用C++写的。 C# 层调用 native 库并提供指向某个托管缓冲区的指针。
几个问题:
如何确保不存在竞争?在这种情况下, native 库中的
std::mutex
是否足够? (托管线程是否映射到 native 线程?它们会共享相同的std::mutex
吗?)如何确保 GC 不会在 native 库操作托管缓冲区时释放指向托管缓冲区的指针?
最佳答案
- 你需要一个共享缓冲区吗?如果缓冲区只在一个线程上使用,您就可以省去很多麻烦。托管线程不会 1:1 映射到 native 线程,但我不确定这是否对您的方案有任何影响。
- 您需要修复缓冲区,并在 native 代码有指向它的指针的整个过程中保持其固定 - 释放是您最不担心的事情,.NET 内存一直在移动。这是使用
fixed
block 完成的。
修复托管内存:
byte[] theBuffer = new byte[256];
fixed (byte* ptr = &theBuffer[0])
{
// The pointer is now fixed - the GC is prohibited from moving the memory
TheNativeFunction(ptr);
}
// Unfixed again
但是,请注意,禁止 GC 移动内存会给您带来很多麻烦 - 例如,它可能会在高吞吐量服务器中完全阻止堆压缩。
如果您不需要在托管环境中使用内存,您可以简单地为任务分配非托管内存,例如使用 Marshal.AllocHGlobal
。
关于c# - 调用 native 代码的多线程托管应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30347128/