C#上的NOINTERFACE
嗨堆栈溢出成员,
我是C#编程的新手。 我正在开发基本的照相机流媒体并仍然捕获应用程序。 一旦用户静止,我将使用VMR9的位图混合概念在叠加层上显示它。
我做了什么?
我面临什么问题?
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函数的代码块
//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);
}
}
}
这里是等待更新事件的线程。
Thread overlayupdatethreadhandle = new Thread(new ThreadStart(overlayupdatethread));
overlayupdatethreadhandle.Start();
private void overlayupdatethread()
{
do
{
overlayupdateeventhandle.WaitOne();
ShowHideBitmap(GlobalVar.m_ShowOverlay);
} while (true);
}
我已经尝试使用在100ms间隔的背景下运行的计时器来更新此覆盖。 使用定时器运行良好,但对于此操作,使用定时器是不好的选择。 所以我移动了线程概念。
为什么从线程调用时获取接口失败,并且从菜单选项调用时工作良好? 我应该照顾任何特殊的事情吗? 我甚至尝试过参数化线程,但没有运气。
在此先感谢您的帮助。
编辑:如果ShowHideBitmap从主线程调用,每件事情都很好。 如果从工作线程调用ShowHideBitmap,则COM对象会创建Exception。 如何处理这个跨线程操作?
例外情况很糟糕,在COM中并不罕见。 它的真正含义是“我不知道如何给你一个你可以在工作线程中使用的接口引用”。 这是一种常见的事故,这些COM组件根本不是线程安全的。 他们通过照顾它来强制执行该操作,将工作线程的调用自动封送到所有者线程。 或者不要让你从另一个线程中使用它们,因为编组会变得毫无意义,从而导致它太慢。 VMR属于后一类。
这与.NET非常不同,它也有很多完全线程不安全的类。 基本的东西,例如,没有任何集合类。 但它可以让你在一个线程中使用这些类,让它保持线程安全。 这当然经常出错,使用适当的锁定是一种技巧。
COM通过设计始终是线程感知的。 有了这样的哲学,线程是很难得到正确的,所以它应该由聪明的人来照顾。 95%的时间非常有效。 剩下的时间给你一个主要的偏头痛。 当COM处理穿线时,由于难以诊断差的性能而引起的那种偏头痛。 当它不这样做时,会报告糟糕的错误。
那么,无法做到,您确实必须使用创建VMR实例的同一线程中的该接口。 没办法。
尝试使用Delphi库中的Listener / Event处理程序对象时,出现错误E_NOINTERFACE。 为了解决编组和不同线程的问题,我保存了分配监听器的线程调度程序,然后使用它来激发事件。
接口:
[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; }
}
然后执行(通知Dispatcher.CurrentDispatcher存储)
[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;
}
}
}
然后在代码中:
if (Listener != null)
{
m_dispatcherListener.Invoke((Action)delegate()
{
Listener.OnTerminateCompleted((int)TerminateStatus.Completed);
});
}
如果Listener在不同的线程中被调用,则不会产生错误
链接地址: http://www.djcxy.com/p/70265.html上一篇: NOINTERFACE on C#