CLI DLL 的本机库中互斥锁的解决方法

use*_*517 5 multithreading mutex c++-cli

我正在为本机 C++ 库编写 C++/CLI 包装器。在返回给 CLI 包装器的类之一中,使用线程,特别#include <mutex>是在标头中定义类级别互斥锁。

问题是,一旦将标头引入 CLI 代码(启用了 /clr 选项),我就会收到在<mutex>使用 /clr 或 /clr:pure 编译时不受支持的错误。

阅读这篇文章How to implement a unmanaged thread-safe collection when I get this error: <mutex> is not supported when compiling with /clr,有一篇博客文章提到了一些可能的解决方法。但是,变通方法假设您不需要任何会导致冲突的头文件,并且所有这些都可以在类函数中完成,基本上是从 CLI 应用程序中隐藏线程函数。

在类级别互斥锁的情况下,情况并非如此。它必须在标题中。

有什么方法可以使 CLI 应用程序与线程化的本机库一起工作?

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

我对不得不合并 ZMQ 之类的东西感到畏缩,因为这是在一个关键部分,现在拥有三个数据副本(可能非常大)将令人望而却步。(一个在托管端,一个在本地,一个通过 ZMQ 中的消息缓冲区)。我知道 ZMQ 的零拷贝,但没有尝试在托管和非托管 C++ 之间进行 inproc 以查看是否可以共享内存。如果可能,它可能需要在整个应用程序中使用低级别连续数据结构,否则会遭受再次复制数据的后果。

那里有没有像样的解决方案的向导?

小智 0

我之前研究过 std::thread 的这个问题,发现以下内容有效。由于 CLR 不允许您std::thead在编译时包含,因此您可以尝试仅在链接时使用它。通常,您可以通过在标头中向前声明该类并仅将它们包含在您的 cpp 文件中来解决此问题。但是,您可以在头文件中转发声明您自己的类,但不能在命名空间 std 中声明您自己的类。根据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:

    };
}
Run Code Online (Sandbox Code Playgroud)

在您想要使用线程的头文件中,您可以向前声明它,如下所示:

#pragma once

// Forward declare the thread class 
namespace Threading { class Thread; }
class ExampleClass
{
    public:
        ExampleClass();
        void ThreadMethod();
    private:
        Threading::Thread * _thread;
};
Run Code Online (Sandbox Code Playgroud)

然后,您可以在源文件中使用主题类,例如:

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

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

void ExampleClass::ThreadMethod()
{
}
Run Code Online (Sandbox Code Playgroud)

您应该能够对 std::mutex 执行相同的操作。希望它可以帮助任何人。

原帖:使用 clr 和 std::thread