2013-03-27 14 views
7

Merhaba Yığın Taşma üyeleri,QueryInterface, E_NOINTERFACE ile çalışmıyor C#

Ben C# programlama için yeni biriyim. Temel bir kamera akışı geliştiriyorum ve yine de uygulamayı yakaladım. Kullanıcı hala harekete geçtikten sonra, VMR9'un bitmap karıştırma konseptini kullanarak bunu üst üste görüntüleyeceğim.

Yaptıklarımı?

  • ben here
  • Birinci gerekli tüm filtreler arabirimleri C# direkt gösteri kütüphanesinin kullanımını olsun yapıyorum. Ekli yakalama cihazını bulun. Kaynak filtre ile Render akışı ve PREVIEW pin için vmr9 olarak adlandırıldı. Kaynak filtresi, örnek kapmak ve STILL PIN için null renderer.
  • Üç menü düğmesi kullanıyorum -> hala al, bindirmeyi göster ve bindirmeyi gizle.
  • Bu kitaplıkta sağlanan bitmap karıştırıcı örneğini kullanıyorum.
  • Kullanıcı Take Still menüsüne her bastığında, görüntü masaüstüne kaydedilir ve yeniden küçük boyutlu olarak yeniden boyutlandırılır ve video bindirmesinde görüntülenir.
  • Yerleşimi göster ve bindirme çağrılarını gizleme VMH9BitmapMixer arabiriminin vmr9 filtresinden sorgulanmasını gerçekleştiren ShowHideBitmap() öğesini VMR9AlphaBitmap yapısını doldurur ve ardından IVMRMixerBitmap9.SetAlphaBitmap işlevini çağırır.

Hangi sorunla karşılaşıyorum? Ben menü seçeneği ile ShowHideBitmap() ararsanız

  • hala aldıktan sonra, alınan hareketsiz görüntü bindirmesi üzerinde mükemmel güncellenmektedir.
  • Bu, hareketsiz görüntü kaydedildiğinde otomatik yer paylaşımını otomatik olarak gerçekleştiren başka bir seçenektir. Etkinlik tabanlı iş parçacığı oluşturup EventWaitHandle kullanılarak oluşturulan güncelleme olayını beklemeyi başardım. Samplegrabber BufferCB işlevinden dönmeden önce bu güncelleştirme olayını ayarlıyorum. Sırayla bekleyen iplik ile devam eder. İç iş parçacığı ShowHideBitmap işlevini çağırırım. Bu senaryoda, aşağıdaki gibi hata iletisi alıyorum. İşte

    Unable to case COM object of type 'DirectShowLib.VideoMixingRenderer9' to interface type 'DirectShowLib.IVMRMixerBitmap9'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{ced175e5-1935-4820-81bd-ff6ad00c9108}' failed due to the following error: No such interface supported (Exception from HRESULT: 0X80040002 (E_NOINTERFACE)

ShowHideBitmap işlevinin kod bloğu

//Declarations 
private static IBaseFilter vmr9 = null; 
private static IVMRMixerBitmap9 vmr9mixerBitmap = null; 
private IVMRWindowlessControl9 vmr9windowlessCtrl = null; 

private static void ShowHideBitmap(Boolean bEnable) 
{ 
int hr = 0; 
VMR9AlphaBitmap alphaBmp; 

if (!bEnable) 
{ 
    if (vmr9mixerBitmap != null) 
    { 
     // Get current Alpha Bitmap Parameters 
     hr = vmr9mixerBitmap.GetAlphaBitmapParameters(out alphaBmp); 
     DsError.ThrowExceptionForHR(hr); 

     // Disable them 
     alphaBmp.dwFlags = VMR9AlphaBitmapFlags.Disable; 

     // Update the Alpha Bitmap Parameters 
     hr = vmr9mixerBitmap.UpdateAlphaBitmapParameters(ref alphaBmp); 
     DsError.ThrowExceptionForHR(hr); 

     // Create a surface from our alpha bitmap 
     surface.Dispose(); 

     vmr9mixerBitmap = null; 

     //Release this alpha bitmap source. 
     if (alphaBitmap != null) 
     { 
      alphaBitmap.Dispose(); 
     } 
    } 
    return; 
} 
else 
{ 
    try 
    { 
     alphaBitmap = BitmapGenerator.GenerateAlphaBitmap(); 

     // Create a surface from our alpha bitmap 
     if(surface == null) 
      surface = new Surface(device, alphaBitmap, Pool.SystemMemory); 

     // Get the unmanaged pointer 
     unmanagedSurface = surface.GetObjectByValue(DxMagicNumber); 

     if (vmr9mixerBitmap == null) 
      vmr9mixerBitmap = (IVMRMixerBitmap9)vmr9; 


     // Set Alpha Bitmap Parameters for using a Direct3D surface 
     alphaBmp = new VMR9AlphaBitmap(); 
     alphaBmp.dwFlags = VMR9AlphaBitmapFlags.EntireDDS; 
     alphaBmp.pDDS = unmanagedSurface; 
     alphaBmp.rDest = GetDestRectangle(); 
     alphaBmp.fAlpha = 1.0f; 

     // Set Alpha Bitmap Parameters 
     hr = vmr9mixerBitmap.SetAlphaBitmap(ref alphaBmp); 
     DsError.ThrowExceptionForHR(hr); 
    } 
    catch (Exception ex) 
    { 
     MessageBox.Show(ex.Message); 
    } 
} 
} 

Ve burada iplik güncelleme olayı için bekler olduğunu.

Thread overlayupdatethreadhandle = new Thread(new ThreadStart(overlayupdatethread)); 
      overlayupdatethreadhandle.Start(); 

    private void overlayupdatethread() 
    { 
     do 
     { 
      overlayupdateeventhandle.WaitOne(); 
      ShowHideBitmap(GlobalVar.m_ShowOverlay); 
     } while (true); 
    } 

Arka planda çalışan, 100 ms aralıklarla çalışan zamanlayıcıyı kullanarak bu yerleşimi güncelleştirmeyi denedim. Zamanlayıcıyı kullanmak iyi çalışıyordu, ancak bu işlem için zamanlayıcıyı kullanmak kötü bir seçimdir. Bu yüzden iş parçacığı konsepti ile taşındım.

Bu özellik, iş parçacığından arama yaparken başarısız oluyor ve menü seçeneklerinden arama yaparken iyi çalışıyor mu? Özel bir şeyle ilgilenmem gerekiyor mu? Parametrized ipliği denedim, ama şans yok. Yardımlarınız için şimdiden

teşekkürler.

DÜZENLEME: Ana iş parçacığından ShowHideBitmap çağrılırsa, her şey düzgün çalışır. Çalışan iş parçacığından ShowHideBitmap çağrılırsa, COM nesnesi özel durum oluşturur.Bu çapraz iş parçacığı işlemek nasıl?

+0

+1. güzel soru. Tamamen emin olmadığım için yorum yap ... Beklenilen sıralama: Çoğu COM nesnesinin tek bir iş parçacığından çağrılması beklenir ... Birden çok iş parçacığı olarak çağırabilirseniz, belgelerinizin büyük olasılıkla açıkça çağırması gerekir. (Ayrıca, nesne çapraz iş parçacığına erişmeden önce diğer iş parçacığı üzerinde COM başlatmanız gerekebileceğini de hatırlıyorum). –

+0

Merhaba Alexei, evet haklısın. Ana iş parçacığı dışındaki birden çok iş parçacığından COM nesnesinin çağrılması bu hatayı oluşturuyor. Hatta bu vmr9mixerBitmap arabirimini başlatmayı denedim Ana iş parçacığı ve aynı ShowHideBitmap işlevini kullanarak (Bu işlevde oluşturmak yerine), ancak sonuç aynıdır. COM başlatmak, ana iş parçacığı arabirimi almalı ve iş parçacığı boyunca aynı arabirimi kullanmalıyım? İş parçacığı üzerinden erişilen bu COM nesnesinin ayrıntılı açıklaması var mı? – Spark

+0

Temel VMR arabirimleri, COM kurallarını ihlal eden öğeler arasında iletilebilir. Yerel kodda olsa da, yönetilmeyen. C# COM interopunda bu kirli hilelerin farkında değil ve bunun bir sorun olabileceğini varsayalım: arayüzü marşlamayla geçmeye çalıştığında, bunu yapamaz, arayüzleri kaybeder ve bunları kullanamazsınız. iş parçacığı üzerinde. –

cevap

3

İstisna, COM'da yaygın olmayan, farelidir. Gerçekten anlamı, "Bir çalışan iş parçacığından kullanabileceğiniz bir arabirim referansı nasıl vereceğimi bilmiyorum". Sık rastlanan bir tür aksaklık olan bu tür COM bileşenleri sadece vida dişi değildir. Ve bunu ya gözeterek, işçinin iş parçacığından çağrıları otomatik olarak iş parçacığına dönüştürerek zorlarlar. Ya da onları başka bir iş parçacığından kullanmanıza izin vermeyerek, çünkü marshalingin anlamsız olacağını ve bu sayede çok yavaş kaldığını. VMR, ikinci kategoriye girer.

Bu, .NET'ten çok farklıdır; ayrıca, tümüyle iş parçacığı güvensiz olan bir lot sınıfına sahiptir. Temel şeyler de, koleksiyon sınıflarının hiçbiri örnek değildir. Ancak, bu sınıfları yine de bir thread içinde kullanmanıza izin verir, böylece iplik güvenli hale getirmek için size bırakılır. Bu oldukça sık yanlış olur, düzgün kilitleme kullanmak bir beceridir.

COM tasarım tarafından her zaman iş parçacığı tarafından biliniyor. Diş çekme işinin doğru olması çok zor olduğu felsefesiyle, akıllı insanlar tarafından ele alınmalıdır. Hangi zamanın fevkalade% 95'inde çalışıyor. Ve zamanın geri kalanında büyük bir migren verir. COM'un iş parçacığı ile uğraşırken zayıf bir zaafı teşhisi zor olan migren türü. Ve ne zaman yapmazsa berbat hata raporlama.

Peki, hayır, gerçekten bu arabirimi, VMR örneğini oluşturan aynı iş parçacığından kullanmak zorundasınız. Bunun bir yolu yok.

+0

Merhaba Hans, Lot testinden sonra döndüm. Belirttiğiniz gibi, şimdi uygulama herhangi bir sorunla neredeyse iki gün için iyi çalışıyor. Kodda herhangi bir değişiklik yapmadım, böyle bıraktım ve ertesi gün test ettim. Aniden sorunsuz çalıştı.Daha fazla bilgi edinmek için bu sorunu yeniden oluşturmaya çalışıyorum. Kısa zamanda sana geri döneceğim. Etkili ve değerli yorumlarınız için teşekkür ederiz :-) – Spark

1

Delphi kitaplığından Dinleyici/Olay işleyicisi nesnesini kullanmaya çalışırken hata E_NOINTERFACE vardı. & numaralı iş parçacığı ile ilgili sorunların üstesinden gelmek için dinleyiciyi atayan iş parçacığı kaydettim ve ardından olayları tetiklemek için kullanıyorum.

Arabirimler:

[ComVisible(true)] 
[Guid("2FFC2C20-A27B-4D67-AEA3-350223D3655F")] 
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
public interface IDataSystemInterfaceEventListener 
{ 
    void OnIntializeCompleted(int status); 
    void OnTerminateCompleted(int status); 
    void OnRunCompleted(int status); 
} 

[ComVisible(true)] 
[Guid("B9953413-A8C9-4CE2-9263-B488CA02E7EC")] 
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
public interface IDataSystemInterface 
{ 
    void Intialize(string config); 
    void StartRun(string conditions); 
    void StopRun(); 
    void Terminate();   

    IDataSystemInterfaceEventListener Listener { get; set; } 
} 

Ardından uygulama kodunda Sonra

[ComVisible(true)] 
[Guid("0818F830-DA37-4167-BF31-3A2C55A9BF2B")]   
public class DataSystemModule : IDataSystemInterface 
{ 
    private Dispatcher m_dispatcherListener = null; 
    private IDataSystemInterfaceEventListener m_listener = null; 
    public IDataSystemInterfaceEventListener Listener 
    { 
     get 
     { 
      return m_listener; 
     } 
     set 
     { 
      m_dispatcherListener = Dispatcher.CurrentDispatcher; 
      m_listener = value; 
     } 
    } 
} 

(haber Dispatcher.CurrentDispatcher saklanan): Dinleyici farklı bir iş parçacığı dispacther olmadan

if (Listener != null) 
{ 
    m_dispatcherListener.Invoke((Action)delegate() 
    { 
     Listener.OnTerminateCompleted((int)TerminateStatus.Completed); 
    }); 
} 

denir eğer

hata üretecek