当前位置:编程学习 > C#/ASP.NET >>

C#调用摄像头无法重复启动,点开第一次,没问题,但是如果再点第二次就会报错,怀疑资源没有释放,请高手指点

其中这个代码是报错的部分,我在第一次打开视频的时候,一点问题没有,但是当把窗体的子窗口关闭,再次打开的时候就会报出错误,hr就会变为负值,希望大家可以给出解决的办法吧,谢谢了 
这代码主要是实现显示摄像头的图像显示,自己琢磨了好久了也解决不了,希望大家帮忙吧 
                Guid cat = PinCategory.Preview; 
                //设置媒体类型为视频帧 
                Guid med = MediaType.Video; 
                //输出视频流 
                hr = capGraph.RenderStream(ref cat, ref med, capFilter, null, null); 
完整的程序代码如下: 
        ///  
        /// 构建Capture Graph 
        /// 
        bool SetupGraph() 
        { 
            int hr; 
            try 
            { 
                //创建Capture Graph Builder组件graphBuilder,并初始化 
                hr = capGraph.SetFiltergraph(graphBuilder); 
                if (hr < 0) 
                    Marshal.ThrowExceptionForHR(hr); 
                //通过AddFilter将graphBuilder组件添加到视频捕获设备capFilter中 
                hr = graphBuilder.AddFilter(capFilter, "视频驱动"); 
                if (hr < 0) 
                    Marshal.ThrowExceptionForHR(hr); 

                //DsUtils.ShowCapPinDialog( capGraph, capFilter, this.Handle ); 
                //设置媒体类型 
                AMMediaType media = new AMMediaType(); 
                media.majorType = MediaType.Video; 
                media.subType = MediaSubType.RGB24; 
                media.formatType = FormatType.VideoInfo; 
                hr = sampGrabber.SetMediaType(media); 
                if (hr < 0) 
                    Marshal.ThrowExceptionForHR(hr); 
                //将graphBuilder添加到baseGrabFlt中 
                hr = graphBuilder.AddFilter(baseGrabFlt, "Ds.NET Grabber"); 
                if (hr < 0) 
                    Marshal.ThrowExceptionForHR(hr); 
                //选择Preview 输出Pin 
                Guid cat = PinCategory.Preview; 
                //设置媒体类型为视频帧 
                Guid med = MediaType.Video; 
                //输出视频流 
                hr = capGraph.RenderStream(ref cat, ref med, capFilter, null, null); 
                if (hr < 0) 
                    Marshal.ThrowExceptionForHR(hr); 
                //选择Capture输出Pin 
                cat = PinCategory.Capture; 
                //选择Capture输出Pin 
                med = MediaType.Video; 
                //输出视频流 
                hr = capGraph.RenderStream(ref cat, ref med, capFilter, null, baseGrabFlt); 
                if (hr < 0) 
                    Marshal.ThrowExceptionForHR(hr); 
                //以下代码实现视频帧捕捉功能 
                media = new AMMediaType(); 
                hr = sampGrabber.GetConnectedMediaType(media); 
                if (hr < 0) 
                    Marshal.ThrowExceptionForHR(hr); 
                if ((media.formatType != FormatType.VideoInfo) || (media.formatPtr == IntPtr.Zero)) 
                    throw new NotSupportedException("Unknown Grabber Media Format"); 

                videoInfoHeader = (VideoInfoHeader)Marshal.PtrToStructure(media.formatPtr, typeof(VideoInfoHeader)); 
                Marshal.FreeCoTaskMem(media.formatPtr); media.formatPtr = IntPtr.Zero; 

                hr = sampGrabber.SetBufferSamples(false); 
                if (hr == 0) 
                    hr = sampGrabber.SetOneShot(false); 
                if (hr == 0) 
                    hr = sampGrabber.SetCallback(null, 0); 
                if (hr < 0) 
                    Marshal.ThrowExceptionForHR(hr); 

                return true; 
            } 
            catch (Exception ee) 
            { 
                LOG.Error(ee.ToString()); 
                MessageBox.Show(this, "不能启动视频\r\n" + ee.Message, "系统提示:", MessageBoxButtons.OK, MessageBoxIcon.Stop); 
                CloseInterfaces(); 
                return false; 
            } 
        }
-----------------------------------------------
释放资源是以下代码,可能还是释放的时候某些资源没有释放掉,所以才会出现问题,望各位大哥给提出宝贵意见! 
        /// <summary> 
        /// 清理并释放DirectShow. 
        /// </summary>        
        void CloseInterfaces() 
        { 
            int hr = 0; 
            try 
            { 
                lock (this) 
                { 
                    if (mediaEvt != null) 
                    { 
                        hr = this.mediaEvt.SetNotifyWindow(IntPtr.Zero, 0, IntPtr.Zero); 
                        //DsError.ThrowExceptionForHR(hr); 
                    } 
                    // Release and zero DirectShow interfaces 
                    if (rotCookie != 0) 
                    { 
                        DsROT.RemoveGraphFromRot(ref rotCookie);                        
                    } 
                    if (mediaCtrl != null) 
                    { 
                        hr = mediaCtrl.Stop(); 
                        mediaCtrl = null; 
                    } 
                    if (mediaEvt != null) 
                    { 
                        hr = mediaEvt.SetNotifyWindow(IntPtr.Zero, WM_GRAPHNOTIFY, IntPtr.Zero); 
                        mediaEvt = null; 
                    } 

                    if (videoWin != null) 
                    { 
                        hr = videoWin.put_Visible(DsHlp.OAFALSE); 
                        hr = videoWin.put_Owner(IntPtr.Zero); 
                        videoWin = null; 
                    } 

                    baseGrabFlt = null; 
                    if (sampGrabber != null) 
                        Marshal.ReleaseComObject(sampGrabber); sampGrabber = null; 
                    
                    if (capGraph != null) 
                        Marshal.ReleaseComObject(capGraph); capGraph = null; 
                    
                    if (graphBuilder != null) 
                        Marshal.ReleaseComObject(graphBuilder); graphBuilder = null; 
                    
                    if (capFilter != null) 
                        Marshal.ReleaseComObject(capFilter); capFilter = null; 
                    
                    if (capDevices != null) 
                    { 
                        foreach (DsDevice d in capDevices) 
                            d.Dispose(); 
                        capDevices = null; 
                    } 
                    GC.Collect(); 
                } 
            } 
            catch (Exception) 
            { } 
        } --------------------编程问答-------------------- 没有仔细看,不过肯定是没有释放干净(我认为,呵呵),帮顶了。 --------------------编程问答-------------------- 大概看了一下,好象該釋放的都釋放了,要試一下換個角度查問題 --------------------编程问答-------------------- 你的这个 CloseInterfaces() 
函数是不是没有调用,你可以在切换是或不使用摄像头时进行调用 --------------------编程问答-------------------- 帮顶了 --------------------编程问答-------------------- 路过帮顶  ing.... --------------------编程问答-------------------- C++ 最后要加上这个,在return 前,要不下次用不了.你应该没加,我也有遇到过. --------------------编程问答-------------------- 帮顶 --------------------编程问答-------------------- 牛帖要有牛人回 --------------------编程问答-------------------- 同样问题啊,求指导啊,呜呜,谢谢啦
--------------------编程问答-------------------- 什么叫做“资源没有释放掉”?这个成了万金油随便抹了。你确切知道需要“释放”什么东西的时候才去释放它,否则在根本没有必要花正规程序处理的时间和空间(而不是GC程序的时间和空间)去处理它,才是不应该的。


.net摄像头的,你打开之前就要关闭一次,不管之前有没有关闭过。这是底层的要求。 --------------------编程问答-------------------- 切记在没有必要的时候不要随便纠结什么“资源释放”,不然你会得编程强迫症。 --------------------编程问答--------------------
引用 11 楼 sp1234 的回复:
切记在没有必要的时候不要随便纠结什么“资源释放”,不然你会得编程强迫症。


+++ --------------------编程问答--------------------
引用 10 楼 sp1234 的回复:
什么叫做“资源没有释放掉”?这个成了万金油随便抹了。你确切知道需要“释放”什么东西的时候才去释放它,否则在根本没有必要花正规程序处理的时间和空间(而不是GC程序的时间和空间)去处理它,才是不应该的。


.net摄像头的,你打开之前就要关闭一次,不管之前有没有关闭过。这是底层的要求。
++  这个是最简单也直接的    个人觉得 搞程序 简单的就是最好的
补充:.NET技术 ,  C#
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,