从C#线程调用非托管代码

时间:2011-02-26 22:25:13

标签: c# c++ multithreading dll managed

我有一个非托管C ++库,我已经为其创建了托管C ++包装器。我现在试图用C#来调用它。到现在为止还挺好。但是,当我尝试在C#线程中从内部调用相同的代码时,我从非托管代码中获得异常:

表达式:向量下标超出范围

这甚至可能吗?我假设每个线程都会得到它自己的非托管类的实例?

我已经搜索了很多关于从线程内调用非托管代码的更多信息,但信息似乎至少可以说是sparce。

提前感谢您提供任何帮助

C ++ Wrapper

// Managed wrapper
public ref class EllipseFit
{
   private:
       // Pointer to unmanaged class
   UnmanagedEllipseFit* _unmanagedEllipseFit;

   public:

       // Constructor & Destructor
   EllipseFit() 
   {
       _unmanagedEllipseFit = new UnmanagedEllipseFit();
       }

   ~EllipseFit() 
   { 
       delete _unmanagedEllipseFit; 
   }

       List<Ellipse^>^ ProcessImage(array<Byte>^ image, int width, int height)
       { 
           pin_ptr<unsigned char> pimg = &image[0];
       _unmanagedEllipseFit->processsImage(pimg, width, height); 

           // Marshal the results... <edited>
       return ellipses;
       }
};

C#Thread

    private void DcThread()
    {
        EllipseFit ellipseFit = new EllipseFit();

        string fullPath = _fileList.GetNext();
        while (fullPath != null)
        {
            // Load the image
            Bitmap bitmap = new Bitmap(fullPath);
            byte[] imageData = TsImage.ConvertBitmap(bitmap);

            // Process
            List<DcEllipse> ellipses = ellipseFit.ProcessImage(imageData, bitmap.Width, bitmap.Height);

            // Save the associated text file.. (Debug)
            TextWriter textFile = new StreamWriter(fullPath.Replace(".jpg", ".txt"));
            foreach (DcEllipse ellipse in ellipses)
                textFile.WriteLine(String.Format("{0} {1} {2} {3} {4}", ellipse.X, ellipse.Y, ellipse.MajorAxisLength, ellipse.MinorAxisLength, ellipse.Angle));
            textFile.Close();

            fullPath = _fileList.GetNext();
        }
    }

C#Thread Start

Thread t1 = new Thread(DcThread);
t1.Start();

2 个答案:

答案 0 :(得分:1)

.NET中的托管类型遵循相同的规则,无论它们是用C#还是C ++ / CLI编写。

虽然可以为每个线程创建一个新的C ++ / CLI类实例,但如果没有告诉编译器你想要的是什么,它就不会自动发生。

编辑:看看代码,除了内存泄漏之外我没有看到任何问题。 C ++ / CLI类应该同时具有析构函数和终结符,如下所示:

!EllipseFit() 
{ 
    delete _unmanagedEllipseFit; 
    _unmanagedElipseFit = nullptr;
}


~EllipseFit() { this->!EllipseFit(); }

至于崩溃 - 也许非托管代码使用静态或全局变量,因此不能同时从多个线程使用。

答案 1 :(得分:-1)

创建线程时,您可以将公寓状态设置为STA(通常用于与COM交互)

Thread thread = new Thread();
thread.SetApartmentState(ApartmentState.STA);
thread.Start(new ThreadStart(DoWork));