2013-04-19 19 views
6

C# kodumdan aramak istediğim bir dış bileşen (C++) var.C# STAThread COMException

kodu şöyle bir şeydir: Yani sorun ilk başta iyi çalışıyor diyoruz, yani

using System.Text; 
using System.Threading; 
using System.Threading.Tasks; 

namespace dgTEST 
{ 
    class Program 
    { 
     [STAThread] 
     static void Main(string[] args) 
     { 
      ExtComponentCaller extCompCaller = new ExtComponentCaller(); 
      result = extCompCaller.Call(input); 

      Thread t = new Thread(new ThreadStart(() => 
      { 
       try 
       { 
        result = extCompCaller.Call(input); 
       } 
       catch (Exception ex) 
       { 
        Console.WriteLine(ex.ToString()); 
       } 
      })); 

      t.SetApartmentState(ApartmentState.STA); 
      t.Start(); 
      t.Join(); 
     } 
    } 
} 

denilen dış bileşen, ben sonuca döndüm.

Ancak, başka bir iş parçacığında aramayı denediğimde, bir özel durum var: System.InvalidCastException: 'System .__ ComObject' türünde COM nesnesine dönüştürülemiyor .... Bu istisnanın, STAThread nedeniyle attığından eminim. Çünkü [STAThread] özniteliğini Ana işlevden kaldırırsam, aynı durum, dış bileşenlerin ilk çağrısıyla oluşur ve bu da iyi çalıştı.

Bu özel durumdan kurtulmak için bu dış bileşeni başka bir iş parçacığından nasıl arayabilirim?

GÜNCELLEME -------------

Diğer çılgın şey şimdi ortaya çıkar. F5 ile Visual Studio'dan programı başlattığınızda, ilk çağrıda da sorun oluşur, ancak ikili .exe dosyasını doğrudan çalıştırdığımda, (diğer iş parçacığı değil :() çalışıyor. I bırakın ve F5 ile Visual Studio onu başlayarak ilk çağrı tekrar çalışmaya Debug yapı geçin.

Neden olur?

Teşekkür önceden yardım için!

Saygılarımızla, Zoli

+0

STA olarak işaretlediğiniz bir iş parçasında tüm işi yaptığınızda (COM örneği oluştur ve yöntem çalıştır) ne olur?Bu COM nesnesinin kayıt defterinde STA olarak işaretlenmiş olması olasıdır ve farklı COM apartmanlarında (MTA'dan STA'ya veya STA'dan MTA'ya), kodlama biçimindeki bir hatadan dolayı iyi çalışmadığı anlaşılmaktadır. –

+0

Aynı özel durumu aldım :(. Ancak Ana işlev, iş parçacığının oluşturulduğu STA'dır. İş parçacığı STA'ya da ayarlanmış, bu yüzden anlamıyorum. –

+0

Bu, bileşendeki bir hatadan kaynaklanabilir. her şey tek bir STA iş parçacığında yapılır, çalışmalıdır –

cevap

2

İş parçacığı hiçbir zaman küçük bir ayrıntı değildir. iş parçacığı desteklemek için bildirilen% 99'luk oran, bunu desteklememesidir.

Ve açıkça bu bileşen iş parçacığı desteklemiyor. Başka bir STA parçacığı oluşturmak sihirli çözüm değildir, hala farklı bir iş parçacığıdır. InvalidCastException, aynı zamanda, oluşturmaya çalıştığınız gibi bir çalışan iş parçacığının çağrılarını düzenlemek için gereken proxy/saplama desteğini de eksik olduğunu söyler. İş parçacığı güvenli olmayan kodlara işitme güvenli arama yapmak için gereklidir. [STAThread] için sözleşmeyi kırmış olsanız da, bir mesaj döngüsünü pompalamalıdır. İş parçacığı iş parçacığından, iş parçacığı güvenli olmayan bir bileşene çağrı yapılmasına izin veren ileti döngüsüdür. Application.Run() öğesinden bir ileti döngüsü alırsınız.

Paranın durduğu yer burasıdır. Diş güvenli değil, dönem. Ana iş parçanızı düzeltmeniz veya satıcının veya yazarımın sizi proxy/saplama ile sağlamasını istemeniz durumunda bile, yapmaya hazır olduğunuz şeyi gerçekleştiremediyseniz, aslında oluşturduğunuz iş parçacığı üzerinde çalışmayacaktır. Yani şuna benzer gerekir: bu yüzden iş parçacığı güvenli olduğu gelen arama yapmak aynı iş parçacığı üzerinde nesne oluşturur

static void Main(string[] args) 
    { 
     Thread t = new Thread(new ThreadStart(() => 
     { 
      ExtComponentCaller extCompCaller = new ExtComponentCaller(); 
      result = extCompCaller.Call(input); 
     })); 

     t.SetApartmentState(ApartmentState.STA); 
     t.Start(); 
     t.Join(); 
    } 

. Bu iş parçacığının bir ileti döngüsünü pompalamaması sorunu hala var, COM bileşenleri buna güveniyor. Bu bir sorun olup olmadığını deadlock veya çalışmayan olaylardan olup olmadığını öğreneceksiniz. Eğer test programınızda ana iş parçacığından aradığınızda daha önce işe yararsa, o zaman muhtemelen pompalamamanız yeterlidir.

+0

Çok iyi açıklama, yardım için teşekkürler! :) Şimdi test programımda çalışıyor. Ben gerçek ortama koyacağım ve her şeyin iyi olacağını ümit ediyorum :). –