How can I mix the Concurrency Runtime with .NET co

2019-02-15 00:09发布

问题:

I've been using the Concurrency Runtime in a C++ static library, and recently wanted to use this library in a C++/CLI project, to take advantage of the Windows Form designer and avoid MFC. Unfortunately, the Concurrency Runtime is not compatible with the /clr switch required in C++/CLI. I tried surrounding the included header files that use the Concurrency Runtime in the "#pragma unmanaged ... #pragma managed" directives, but while that's worked for me with other code in the past, it doesn't seem to work in this case. By which I mean that I get the error:

C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\concrt.h(27): fatal error C1189: #error :  ERROR: Concurrency Runtime is not supported when compiling /clr.

I'm not super well versed in mixing managed and unmanaged code, so it's possible that there's a work-around that I'm not aware of. But on the other hand, perhaps this is just a silly approach. If it weren't for the fact that I find MFC impossibly complex, and the Form designer so nice and easy, I'd just do pure C++. With a preference to mixing the two, any suggestions?

回答1:

Using ConcRT in C++/CLI is explicitly disabled in concrt.h via the statement below because it is not officially supported...

#if defined(_M_CEE)
   #error ERROR: Concurrency Runtime is not supported when compiling /clr.
#endif

You can use PInvoke to work around this as suggested above, or you can also use the pointer to implementation idiom to address this by forward declaring a 'pimpl' class and hide the dependency on concrt.h to a native .cpp file which you can then compile into a lib and link against with the header file.

e.g. in the .h file:

//forward declaration
class PImpl;

class MyClass
{
  ....
  //forward declaration is sufficient because this is a pointer
  PImpl* m_pImpl;
}

e.g. in your .cpp file which compiles into a native lib:

  #include <ppl.h>
  class PImpl
  {
   //some concrt class
   Concurrency::task_group m_tasks;
  }


回答2:

You could consider writing a managed GUI, and have it invoke (using PInvoke) an unmanaged DLL: if you can package the Concurrency Runtime, and the code which uses it, as a DLL.



回答3:

I'm not sure how detailed your concurrent needs are, but OpenMP works fine (i.e., you can combine options /clr and /openmp)

array<MyModelResult^>^ model ....;
#pragma omp parallel for
for(int i=0;i<model->Length;i++) {
    model[i] = ComputeModelFor(i);
}


回答4:

Even if ConcRT in C++/CLI is explicitly disabled, you can have your project compiled with clr support and have some native classes in the same project, by setting CompileAsManaged property to false and PrecompildHeader to NotUsing in your vcxproj file (I've tested this with VS2013):

<ClCompile Include="NativeProcessWithThread.cpp">
  <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged>
  <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
  <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
  </PrecompiledHeaderFile>
  <PrecompiledHeaderOutputFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
  </PrecompiledHeaderOutputFile>
  <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</CompileAsManaged>
  <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
  <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
  </PrecompiledHeaderFile>
  <PrecompiledHeaderOutputFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
  </PrecompiledHeaderOutputFile>
</ClCompile>

Then you can instantiate that class like this from your managed C++ code:

NativeProcessWithThread nativeProcess = NativeProcessWithThread();