2011-02-26 4 views
2

J'ai une bibliothèque C++ non managée pour laquelle j'ai créé un wrapper C++ géré. J'essaye maintenant d'appeler ceci de C#. Jusqu'ici tout va bien. Cependant, lorsque je tente d'appeler le même code à l'intérieur dans un thread C# Je reçois des exceptions à partir du code non managé:Appel de code non géré à partir d'un thread C#

expression: vecteur Indice hors de portée

Est-ce même possible? Je suppose que chaque thread obtiendrait sa propre instance de la classe non managée?

J'ai cherché longtemps et dur pour plus d'informations sur l'appel de code non géré à partir de threads, mais l'information semble sparce pour le moins.

Merci à l'avance pour toute aide

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# Discussion

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# Discussion Début

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

Vous allez devoir montrer une partie du code C++/CLI pour nous de faire QUELQUE sens de ceci. –

+0

* EDIT * Les exceptions ne se produisent que lorsque j'ai plus d'un thread. Dans un fil de lui-même sans autres threads, je ne vois aucune exception. –

+0

Créez-vous explicitement des instances séparées de la classe pour chaque thread? Le partage de la classe wrapper managée ou de la classe native non managée lorsqu'ils ne sont pas conçus pour le multithreading est un gros non-non. –

Répondre

1

types gérés dans .NET suivent le même règles, pas de ma tter s'ils sont écrits en C# ou C++/CLI.

Bien qu'il soit possible de créer une nouvelle instance de la classe C++/CLI pour chaque thread, cela ne se produira pas automatiquement sans que vous indiquiez au compilateur ce que vous voulez.

EDIT: En regardant le code, je ne vois aucun problème en dehors d'une fuite de mémoire. La classe C++/CLI doit avoir à la fois un destructor et finaliseur, comme ceci:

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


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

En ce qui concerne l'accident - peut-être le code non managé utilise des variables statiques ou globales, et donc ne peut pas être utilisé simultanément à partir de plusieurs threads .

+0

Salut Ben, je crée une instance du wrapper géré dans chaque thread. Je ne peux juste pas comprendre pourquoi si chaque thread a sa propre instance je verrais un comportement différent quand je cours plus d'un fil. –

+0

Ahh maintenant .. une variable globale profondément dans le non managé mon code C++ semble avoir été le problème. Merci pour ton aide! –

+1

@user: Vous voulez probablement aussi une instruction 'using' pour vous assurer que l'objet est éliminé rapidement. –

-1

Lorsque vous créez votre fil, vous pouvez définir l'état de l'appartement à STA (généralement utile pour interagir avec COM)

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

Il n'y a pas de COM ici, juste C++ pure interop. –

Questions connexes