2015-05-20 69 views
2

我有一个使用ASP WebApi的服务。每个http请求都转换为需要执行一些数据操作的线程(可能会更改数据)。 API层是用C#编写的,数据操作是用C++编写的。 C#层调用本地库并提供指向某个受管缓冲区的指针。调用本地代码的多线程托管应用程序

几个问题:

  1. 我怎样才能确保有没有比赛?本地库中的std::mutex足够在这种情况下? (做管理线程映射到本地线程吗?它们将共享相同的std::mutex?)

  2. 如何确保GC在本机库正在操作时不释放指向托管缓冲区的指针?

+0

你在做什么,到目前为止你尝试过什么?你为什么要缓冲区被管理? C#和C++都会操纵那个缓冲区吗?缓冲区是每个请求还是共享?什么是缓冲区? – Luaan

+0

@Luaan我们正在尝试尽可能高效地处理大量数据。这就是我们决定用C++来处理它的原因。缓冲区被管理,因为我倾向于尽可能多地使用C#。只有C++操纵数据。缓冲区保存我们的应用程序发送给我们的遥测数据 – Shmoopy

+0

好的......但这意味着只有在您从C#调用C++ interop方法时才会使用缓冲区,对不对?所以你可以处理锁定在C#级别,对吧?它甚至可能使下面的“固定”方法工作得很好,如果你不保留“固定”参考时间太长。 – Luaan

回答

1
  1. 你需要一个共享缓冲区?如果缓冲区只在一个线程中使用,那么你可以节省很多麻烦。托管线程不映射到本地线程1:1,但我不确定这是否对您的方案有任何影响。
  2. 您需要修复缓冲区,并在整个本地代码都有一个指向它的地方固定它 - 释放是您最担心的问题,.NET内存一直在移动。这是通过使用fixed块完成的。

定影管理内存:

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

+0

谢谢。 1.不幸的是,这必须是一个共享缓冲区(我们内存不足,不能复制它2.可以wrl :: ComPtr <>通过管理ref计数来帮助这里吗? – Shmoopy

+0

@Shmoopy我看不到它实际上很容易在C#中安全地处理内存引用和指针 - 例如,您可以从'SafeBuffer'类中派生一个类型;它将为您提供一个安全引用,以便您可以相对轻松地使用非托管内存但如果不知道更多关于整个场景的信息,就很难说更具体的内容。 – Luaan