Multithreading CLI DLL的本机库中的互斥体的解决方法 我正在为一个本地C++库编写一个C++/CLI包装器。在返回到CLI包装器的一个类中,使用thread,特别是#include在头中定义类级互斥体

Multithreading CLI DLL的本机库中的互斥体的解决方法 我正在为一个本地C++库编写一个C++/CLI包装器。在返回到CLI包装器的一个类中,使用thread,特别是#include在头中定义类级互斥体,multithreading,c++-cli,mutex,Multithreading,C++ Cli,Mutex,问题是,一旦将头引入到CLI代码中(启用了/clr选项),我就会得到一个错误,即使用/clr或/clr:pure编译时不支持 在阅读这篇文章时,有一篇博客文章提到了一些可能的解决办法。但是,解决方法假定您不需要任何导致冲突的头文件,所有这些都可以在类函数中完成,本质上是对CLI应用程序隐藏线程函数 对于类级互斥,情况并非如此。它必须在标题中 有没有办法使CLI应用程序与线程化的本机库一起工作 是的,我知道托管代码和非托管代码之间存在GetCurrentThreadID()问题,但正确的方法是什么

问题是,一旦将头引入到CLI代码中(启用了/clr选项),我就会得到一个错误,即使用/clr或/clr:pure编译时不支持

在阅读这篇文章时,有一篇博客文章提到了一些可能的解决办法。但是,解决方法假定您不需要任何导致冲突的头文件,所有这些都可以在类函数中完成,本质上是对CLI应用程序隐藏线程函数

对于类级互斥,情况并非如此。它必须在标题中

有没有办法使CLI应用程序与线程化的本机库一起工作

是的,我知道托管代码和非托管代码之间存在GetCurrentThreadID()问题,但正确的方法是什么?还是没有办法

我对必须合并类似ZMQ的内容感到畏缩,因为这是一个关键部分,现在拥有三份数据副本(可能非常大)将是禁止的。(一个在托管端,一个在本机,另一个通过ZMQ中的消息缓冲区)。我知道ZMQ的零拷贝,但是没有尝试过托管和非托管C++之间的InPro,看看是否可以共享内存。如果可能,可能需要在整个应用程序中使用低级别的连续数据结构,或者再次复制数据


有没有向导提供了一个合适的解决方案?

我以前研究过std::thread的这个问题,我发现下面的方法很有效。由于CLR不允许您在编译时包含
std::thead
,所以您可以尝试仅在链接时使用它。通常,您可以通过在头文件中声明类并仅在cpp文件中包含它们来解决此问题。但是,可以在头文件中向前声明自己的类,但是不能在命名空间标准中声明类。根据C++11标准,17.6.4.2.1:

< > C++程序的行为如果添加声明或是声明,则未定义。 命名空间std或命名空间std中的命名空间的定义 除非另有规定

解决此问题的一个方法是创建一个线程类,该类继承自
std::thread
,您可以向前声明该类。此类的头文件如下所示:

#pragma once
#include <thread>
#include <utility>
namespace Threading
{
    class Thread : std::thread
    {
    public:
        template<class _Fn, class... _Args> Thread(_Fn fn, _Args... args) : std::thread(fn, std::forward<_Args...>(args...))
        {

        }
    private:

    };
}
然后,您可以在源文件中使用如下所示的编码类:

#include "ExampleClass.h"
#include "Thread.h"

ExampleClass::ExampleClass() :
{
    _thread = new Threading::Thread(&ExampleClass::ThreadMethod, this);
}

void ExampleClass::ThreadMethod()
{
}
您应该能够对std::mutex执行相同的操作。希望它能帮助任何人

原始帖子:

解决方案是使用#ifdef在CLI代码中有选择地隐藏.h文件中的互斥声明,但仍在cpp本机代码中编译它

nativeClass.h文件:

#ifdef NATIVE_CODE
    #include <mutex>
#endif

class naticeClass {
public:
    void doSomething();
private:
#ifdef NATIVE_CODE
    mutex _mutex;
#endif

};

下面是我解决这个问题的方法——创建一个自己的互斥锁。我并没有因为旋转等待而对解决方案感到欣喜若狂,但它似乎工作得很好。我只需要保护对std::vector的多线程访问

in .h file:
    std::atomic<int> vectorLock = 0;
in .cpp file:
    while (vectorLock.exchange(1) == 1) {}
         ... critical code goes here
    vectorLock = 0;
.h文件中的

std::原子向量锁=0;
在.cpp文件中:
while(vectorLock.exchange(1)=1{}
... 关键代码在这里
矢量锁=0;

您可以尝试在一个单独的.cpp文件中围绕正在使用的类编写一个PIMPL包装,并在不使用
/clr
变量的情况下编译该.cpp,然后在代码的其余部分而不是原始类中使用该PIMPL包装。这样一来,使用
std::mutex
的任何东西都不会使用
/clr
variant.Hmmm…有趣的想法进行编译。但是,知道GECurrutTrimDad()是否会在本机C++中使用,这是安全的吗?我并没有试图在托管和非托管之间传输线程,所以这似乎不是一个问题。但是,我不确定,调用任何给定的本机函数都不是问题。问题是使用
/clr
变量编译某些代码。混合模式C++/CLI的一般经验法则是使用
/clr
尽可能少地编译代码,只编译必要的互操作位。是的,这就是我试图做的…只是头需要互斥,所以现在我必须隔离它。这不是一件坏事……但现在我必须添加另一层-(平心而论,编写该层几乎是C++/CLI的唯一初衷。.-]
#define NATIVE_CODE 
#include "nativeClass.h"

void nativeClass:doSomething()
{
    _mutex.lock();
    ...

}
in .h file:
    std::atomic<int> vectorLock = 0;
in .cpp file:
    while (vectorLock.exchange(1) == 1) {}
         ... critical code goes here
    vectorLock = 0;